Compare commits

..

60 Commits

Author SHA1 Message Date
georgehao
82f39aa9dc fix bundle task detail bug (#1460) 2024-07-19 23:44:59 +08:00
georgehao
0c106636c2 update zkcircuit (#1457) 2024-07-19 17:48:52 +08:00
georgehao
c87c35629d fix typo (#1456) 2024-07-19 13:23:04 +08:00
georgehao
8f273f7a69 fix coordinator bug (#1455) 2024-07-19 12:33:33 +08:00
Mengran Lan
17b7e5caee Feat/upgrade4 prover print more error (#1454) 2024-07-19 08:23:26 +08:00
colin
07dc2c91bb Merge branch 'develop' into feat/upgrade4 2024-07-19 00:45:46 +08:00
Mengran Lan
4e3a4a42c8 fix(prover): fix too many bytes issue when proving batch (#1453)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2024-07-19 00:38:11 +08:00
colinlyguo
768226c71f Merge branch 'develop' into feat/upgrade4 2024-07-19 00:27:28 +08:00
georgehao
74c197e85a update codec version (#1448)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: Suuuuuuperrrrr fred <FredrikaPhililip@proton.me>
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
Co-authored-by: sbaizet <74511063+sbaizet-ledger@users.noreply.github.com>
Co-authored-by: caseylove <casey4love@foxmail.com>
Co-authored-by: BoxChen <13927203+nishuzumi@users.noreply.github.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
2024-07-19 00:00:45 +08:00
Mengran Lan
f95eaec3ce feat(prover): upgrade darwin's zkevm-circuits branch (#1451) 2024-07-18 23:43:00 +08:00
Mengran Lan
c34883e0aa fix lint issue (#1450) 2024-07-18 23:26:30 +08:00
Mengran Lan
8960d0f32d fix(prover): fix panic issue when trying to get curie's bundle vk (#1449) 2024-07-18 23:13:01 +08:00
georgehao
76a9d6fb20 fix init bundle vk map (#1447) 2024-07-18 20:51:32 +08:00
Rohit Narurkar
8b779ff49a prover(branch): release/v0.12.0 (#1446) 2024-07-18 18:47:23 +08:00
BoxChen
61ab085c82 docs: update README to reflect project structure changes (#1416)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2024-07-18 11:43:06 +08:00
georgehao
d516949f39 fix ProcessPendingBundles record not found (#1444) 2024-07-18 11:38:14 +08:00
Rohit Narurkar
3716c5a436 bump prover (upgrade #4) (#1437) 2024-07-18 10:19:31 +08:00
caseylove
a8e2551d79 ci(Makefile): add missing help msg of Makefile target update (#1440) 2024-07-16 13:52:58 +08:00
georgehao
cfa106291e bump version (#1439) 2024-07-14 05:13:29 +08:00
colin
bfb3c7d2b4 feat(chunk&batch proposers): check compressed data validity (#1431)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2024-07-14 05:07:54 +08:00
colin
f14053ed0c fix(bridge-history): decode commitBatchWithBlobProof calldata (#1429) 2024-07-13 00:20:51 +08:00
sbaizet
0ff897a287 build: add ca-certificates to gas-oracle and rollup-relayer (#1436) 2024-07-12 14:37:19 +02:00
georgehao
04a893a98f feat: enable process pending bundles (#1433)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2024-07-12 11:44:30 +08:00
Mengran Lan
622ce7b0c9 feat(prover): upgrade zkevm-circuits to same as coordinator's with changes of BatchProvingTask & BundleProvingTask (#1434) 2024-07-12 10:56:33 +08:00
georgehao
2392d3458a enable chunk proof verify (#1432) 2024-07-11 20:02:43 +08:00
Rohit Narurkar
a2e8b6a644 libzkp and coordinator updates (preparation for Upgrade4) (#1419)
Co-authored-by: georgehao <haohongfan@gmail.com>
2024-07-11 19:47:02 +08:00
Mengran Lan
3567f5b62a feat(prover): upgrade zkevm-circuits version (#1424) 2024-07-11 15:06:24 +08:00
sbaizet
4e3dc52db3 fix: add ca-certificates on go-rust-builder intermediate image (#1428) 2024-07-11 15:05:55 +08:00
colin
8471838cd4 fix(rollup-relayer): catch errors (#1427) 2024-07-10 22:56:16 +08:00
colin
c812288250 build: update dockerfiles (#1426)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2024-07-10 19:42:27 +08:00
colin
e61a0c3473 fix(rollup-relayer): avoid compressing "small tip" block (#1414)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2024-07-10 18:00:24 +08:00
Suuuuuuperrrrr fred
470a8ed053 Delete dead badge (#1425) 2024-07-10 11:09:40 +02:00
colin
0737d5d3e3 feat(bridge-history): generate withdraw proofs by bundle (#1415) 2024-07-10 11:54:37 +08:00
georgehao
61a3af538d enable push tag to build docker 2024-07-10 10:05:38 +08:00
colin
c758aa6fa4 fix: build coordinator and bridge-history images (#1421) 2024-07-10 09:30:32 +08:00
Mengran Lan
abe66c6f7e feat(prover): supporting upgrade4 (#1412)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2024-07-08 19:32:34 +08:00
colinlyguo
7196c5cab6 Merge branch 'develop' into feat/upgrade4 2024-07-08 19:27:05 +08:00
georgehao
380dbba61d feat(coordinator): upgrade 4 (#1399)
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
Co-authored-by: Mengran Lan <lanmengran@qq.com>
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2024-07-08 18:57:53 +08:00
colin
86aed8e667 chore: decommission event-watcher (#1413) 2024-07-08 17:54:25 +08:00
colin
bc9bc5db36 feat(rollup-relayer): finalize bundle (#1411) 2024-07-08 15:26:50 +08:00
colin
beee0c286c feat(coordinator): enhance batch proof sanity check (#1408)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
Co-authored-by: Mengran Lan <mengran@scroll.io>
Co-authored-by: amoylan2 <amoylan2@users.noreply.github.com>
2024-07-02 16:59:52 +08:00
colin
0b32509a55 Merge branch 'develop' into feat/upgrade4 2024-07-02 16:57:26 +08:00
Xi Lin
ab9c541409 refactor: use submodules for contracts (#1396)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2024-07-02 16:34:40 +08:00
Rohit Narurkar
e679052df1 feat(common): update types as per upgrade4 (#1409)
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
2024-07-02 00:42:29 +08:00
Mengran Lan
16673e2b97 feat(bridge-history): change FinalizeBatch event logic (#1405)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
Co-authored-by: amoylan2 <amoylan2@users.noreply.github.com>
2024-07-02 00:40:04 +08:00
colin
a2536d5613 fix(coordinator): panic (#1407)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2024-06-29 06:01:44 +08:00
colin
5f31d28ced fix(coordinator): get empty task (#1406)
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2024-06-28 23:17:35 +08:00
colin
229809ad6f feat(rollup-relayer): support commitBatchWithBlobProof (#1397) 2024-06-27 21:25:51 +08:00
colin
fb43e87608 feat(rollup-db): add bundle hash (#1401) 2024-06-27 15:00:47 +08:00
colin
54adbb3e77 feat(common): add hardfork util functions supporting both height and timestamp (#1400) 2024-06-27 09:55:07 +08:00
georgehao
664c042a14 Merge branch 'develop' into feat/upgrade4 2024-06-26 21:53:57 +08:00
colin
eada1d05fe fix(Makefile): remove outdated prover in golang-related cmds (#1398) 2024-06-26 14:36:10 +08:00
colin
1a739cd5a7 faet(db): add bundle table (#1395)
Co-authored-by: georgehao <haohongfan@gmail.com>
2024-06-25 10:13:34 +08:00
sbaizet
2f39e37bc2 Ci coordinator api arm64 (#1383) 2024-06-24 09:17:22 +02:00
Zhang Zhuo
d454941c81 chore(libzkp): v0.11.4 (#1391)
Co-authored-by: georgehao <georgehao@users.noreply.github.com>
2024-06-24 09:35:57 +08:00
georgehao
1b6886bb49 init 2024-06-24 09:21:57 +08:00
Mengran Lan
738c85759d feat(prover): add unit test for circuits e2e test (used in test_zkp project) (#1379) 2024-06-18 15:21:26 +08:00
Zhang Zhuo
27d627e318 feat(coordinator & prover): upgrade libzkp to v0.11.3 (#1384)
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2024-06-18 10:39:32 +08:00
Kenn
8c3ecd395f chore: spelling fixes (#1378) 2024-06-18 09:31:20 +08:00
Hsiao_Jan
33016b1d5d fix(db): the function UpdateProvingStatusFailed proving_status determines the condition incorrectly (#1377)
Co-authored-by: xiaoranlu <xiaoranlu@tencent.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2024-06-14 10:01:33 +08:00
423 changed files with 7103 additions and 62718 deletions

View File

@@ -1,138 +0,0 @@
name: Contracts
on:
push:
branches:
- main
- staging
- develop
- alpha
paths:
- 'contracts/**'
- '.github/workflows/contracts.yaml'
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
paths:
- 'contracts/**'
- '.github/workflows/contracts.yaml'
defaults:
run:
working-directory: 'contracts'
jobs:
foundry:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- name: Setup LCOV
uses: hrishikesh-kadam/setup-lcov@v1
- name: Install Node.js 18
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache yarn dependencies
uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('contracts/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Cache node_modules
id: npm_cache
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('contracts/yarn.lock') }}
- name: yarn install
# if: steps.npm_cache.outputs.cache-hit != 'true'
run: yarn install
- name: Compile with foundry
run: forge build --evm-version cancun
- name: Run foundry tests
run: forge test --evm-version cancun -vvv
- name: Run foundry coverage
run : forge coverage --evm-version cancun --report lcov
- name : Prune coverage
run : lcov --rc branch_coverage=1 --remove ./lcov.info -o ./lcov.info.pruned 'src/mocks/*' 'src/test/*' 'scripts/*' 'node_modules/*' 'lib/*'
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
files: contracts/lcov.info.pruned
flags: contracts
hardhat:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Node.js 18
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache yarn dependencies
uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('contracts/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Cache node_modules
id: npm_cache
uses: actions/cache@v2
with:
path: node_modules
key: node_modules-${{ hashFiles('contracts/yarn.lock') }}
- name: yarn install
# if: steps.npm_cache.outputs.cache-hit != 'true'
run: yarn install
- name: Compile with hardhat
run: npx hardhat compile
- name: Run hardhat tests
run: npx hardhat test

View File

@@ -0,0 +1,41 @@
name: Docker-coordinator-api-arm64
on:
workflow_dispatch:
inputs:
tag:
description: "tag of this image (suffix -arm64 is added automatically)"
required: true
type: string
jobs:
build-and-push-arm64-image:
runs-on: ubuntu-latest
strategy:
matrix:
arch:
- aarch64
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
run: |
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker buildx create --name multiarch --driver docker-container --use
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build docker image
uses: docker/build-push-action@v2
with:
platforms: linux/arm64
context: .
file: ./build/dockerfiles/coordinator-api.Dockerfile
push: true
tags: scrolltech/coordinator-api:${{inputs.tag}}-arm64

View File

@@ -9,51 +9,6 @@ env:
AWS_REGION: us-west-2
jobs:
event_watcher:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: check repo and create it if not exist
env:
REPOSITORY: event-watcher
run: |
aws --region ${{ env.AWS_REGION }} ecr describe-repositories --repository-names ${{ env.REPOSITORY }} && : || aws --region ${{ env.AWS_REGION }} ecr create-repository --repository-name ${{ env.REPOSITORY }}
- name: Build and push
uses: docker/build-push-action@v3
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: event-watcher
IMAGE_TAG: ${{ github.ref_name }}
with:
context: .
file: ./build/dockerfiles/event_watcher.Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:latest
${{ env.ECR_REGISTRY }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}
${{ env.ECR_REGISTRY }}/${{ env.REPOSITORY }}:latest
gas_oracle:
runs-on: ubuntu-latest
steps:
@@ -361,7 +316,6 @@ jobs:
with:
context: .
file: ./build/dockerfiles/coordinator-api.Dockerfile
platforms: linux/amd64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}

15
.gitmodules vendored
View File

@@ -1,12 +1,3 @@
[submodule "l2geth"]
path = l2geth
url = git@github.com:scroll-tech/go-ethereum.git
[submodule "contracts/lib/ds-test"]
path = contracts/lib/ds-test
url = https://github.com/dapphub/ds-test
[submodule "contracts/lib/forge-std"]
path = contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "contracts/lib/solmate"]
path = contracts/lib/solmate
url = https://github.com/rari-capital/solmate
[submodule "scroll-contracts"]
path = scroll-contracts
url = https://github.com/scroll-tech/scroll-contracts.git

View File

@@ -1,36 +1,33 @@
.PHONY: fmt dev_docker build_test_docker run_test_docker clean update
L2GETH_TAG=scroll-v5.3.0
L2GETH_TAG=scroll-v5.5.1
help: ## Display this help message
@grep -h \
-E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
update:
update: ## Update dependencies
go work sync
cd $(PWD)/bridge-history-api/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy
cd $(PWD)/common/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG}&& go mod tidy
cd $(PWD)/coordinator/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy
cd $(PWD)/database/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy
cd $(PWD)/prover/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG}&& go mod tidy
cd $(PWD)/rollup/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy
cd $(PWD)/tests/integration-test/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy
lint: ## The code's format and security checks.
lint: ## The code's format and security checks
make -C rollup lint
make -C common lint
make -C coordinator lint
make -C database lint
make -C prover lint
make -C bridge-history-api lint
fmt: ## format the code
fmt: ## Format the code
go work sync
cd $(PWD)/bridge-history-api/ && go mod tidy
cd $(PWD)/common/ && go mod tidy
cd $(PWD)/coordinator/ && go mod tidy
cd $(PWD)/database/ && go mod tidy
cd $(PWD)/prover/ && go mod tidy
cd $(PWD)/rollup/ && go mod tidy
cd $(PWD)/tests/integration-test/ && go mod tidy
@@ -38,11 +35,10 @@ fmt: ## format the code
goimports -local $(PWD)/common/ -w .
goimports -local $(PWD)/coordinator/ -w .
goimports -local $(PWD)/database/ -w .
goimports -local $(PWD)/prover/ -w .
goimports -local $(PWD)/rollup/ -w .
goimports -local $(PWD)/tests/integration-test/ -w .
dev_docker: ## build docker images for development/testing usages
dev_docker: ## Build docker images for development/testing usages
docker pull postgres
docker build -t scroll_l1geth ./common/testcontainers/docker/l1geth/
docker build -t scroll_l2geth ./common/testcontainers/docker/l2geth/

View File

@@ -1,7 +1,6 @@
# Scroll Monorepo
[![rollup](https://github.com/scroll-tech/scroll/actions/workflows/rollup.yml/badge.svg)](https://github.com/scroll-tech/scroll/actions/workflows/rollup.yml)
[![contracts](https://github.com/scroll-tech/scroll/actions/workflows/contracts.yml/badge.svg)](https://github.com/scroll-tech/scroll/actions/workflows/contracts.yml)
[![bridge-history](https://github.com/scroll-tech/scroll/actions/workflows/bridge_history_api.yml/badge.svg)](https://github.com/scroll-tech/scroll/actions/workflows/bridge_history_api.yml)
[![coordinator](https://github.com/scroll-tech/scroll/actions/workflows/coordinator.yml/badge.svg)](https://github.com/scroll-tech/scroll/actions/workflows/coordinator.yml)
[![prover](https://github.com/scroll-tech/scroll/actions/workflows/prover.yml/badge.svg)](https://github.com/scroll-tech/scroll/actions/workflows/prover.yml)
@@ -17,10 +16,9 @@
├── <a href="./common/">common</a>: Common libraries and types
├── <a href="./coordinator/">coordinator</a>: Prover coordinator service that dispatches proving tasks to provers
├── <a href="./database">database</a>: Database client and schema definition
├── <a href="./src">l2geth</a>: Scroll execution node
├── <a href="./prover">prover</a>: Prover client that runs proof generation for zkEVM circuit and aggregation circuit
├── <a href="./rollup">rollup</a>: Rollup-related services
├── <a href="./rpc-gateway">rpc-gateway</a>: RPC gateway external repo
├── <a href="./scroll-contracts">scroll-contracts</a>: solidity code for Scroll L1 bridge and rollup contracts and L2 bridge and pre-deployed contracts.
└── <a href="./tests">tests</a>: Integration tests
</pre>
@@ -52,12 +50,6 @@ go test -v -race -covermode=atomic scroll-tech/database/...
go test -v -race -covermode=atomic scroll-tech/common/...
```
## Testing Contracts
You can find the unit tests in [`contracts/src/test/`](/contracts/src/test/), and integration tests in [`contracts/integration-test/`](/contracts/integration-test/).
See [`contracts`](/contracts) for more details on the contracts.
## License
Scroll Monorepo is licensed under the [MIT](./LICENSE) license.

File diff suppressed because one or more lines are too long

View File

@@ -96,7 +96,7 @@ func action(ctx *cli.Context) error {
return nil
}
// Run event watcher cmd instance.
// Run bridge-history-backend api cmd instance.
func Run() {
if err := app.Run(os.Args); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)

View File

@@ -84,7 +84,7 @@ func action(ctx *cli.Context) error {
return nil
}
// Run event watcher cmd instance.
// Run bridge-history-backend fetcher cmd instance.
func Run() {
if err := app.Run(os.Args); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)

View File

@@ -19,7 +19,7 @@
"ScrollChainAddr": "0xa13BAF47339d63B743e7Da8741db5456DAc1E556",
"GatewayRouterAddr": "0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6",
"MessageQueueAddr": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
"BatchBridgeGatewayAddr": "0x0000000000000000000000000000000000000000"
"BatchBridgeGatewayAddr": "0x5Bcfd99c34cf7E06fc756f6f5aE7400504852bc4"
},
"L2": {
"confirmation": 0,
@@ -39,7 +39,7 @@
"PufferGatewayAddr": "0x9eBf2f33526CD571f8b2ad312492cb650870CFd6",
"GatewayRouterAddr": "0x4C0926FF5252A435FD19e10ED15e5a249Ba19d79",
"MessageQueueAddr": "0x5300000000000000000000000000000000000000",
"BatchBridgeGatewayAddr": "0x0000000000000000000000000000000000000000"
"BatchBridgeGatewayAddr": "0xa1a12158bE6269D7580C63eC5E609Cdc0ddD82bC"
},
"db": {
"dsn": "postgres://postgres:123456@localhost:5444/test?sslmode=disable",

View File

@@ -8,10 +8,10 @@ require (
github.com/go-redis/redis/v8 v8.11.5
github.com/pressly/goose/v3 v3.16.0
github.com/prometheus/client_golang v1.19.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea
github.com/scroll-tech/go-ethereum v1.10.14-0.20240626125436-418bc6f728b6
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.25.7
golang.org/x/sync v0.6.0
golang.org/x/sync v0.7.0
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde
)
@@ -19,7 +19,7 @@ require (
dario.cat/mergo v1.0.0 // indirect
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.12.0 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/bytedance/sonic v1.10.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -36,7 +36,7 @@ require (
github.com/docker/docker v26.1.0+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 // indirect
github.com/ethereum/c-kzg-4844 v1.0.2 // indirect
github.com/fjl/memsize v0.0.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
@@ -57,7 +57,7 @@ require (
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/iden3/go-iden3-crypto v0.0.15 // indirect
github.com/iden3/go-iden3-crypto v0.0.16 // indirect
github.com/jackc/pgx/v5 v5.5.4 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
@@ -65,7 +65,6 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -90,29 +89,28 @@ require (
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/scroll-tech/zktrie v0.8.2 // indirect
github.com/scroll-tech/da-codec v0.0.0-20240718144756-1875fd490923 // indirect
github.com/scroll-tech/zktrie v0.8.4 // indirect
github.com/sethvargo/go-retry v0.2.4 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/supranational/blst v0.3.12 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.17.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect

View File

@@ -23,8 +23,8 @@ github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.12.0 h1:U/q1fAF7xXRhFCrhROzIfffYnu+dlS38vCZtmFVPHmA=
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
@@ -61,7 +61,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0q
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -87,8 +86,8 @@ github.com/elastic/go-sysinfo v1.11.1 h1:g9mwl05njS4r69TisC+vwHWTSKywZFYYUu3so3T
github.com/elastic/go-sysinfo v1.11.1/go.mod h1:6KQb31j0QeWBDF88jIdWSxE8cwoOB9tO4Y4osN7Q70E=
github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0=
github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c=
github.com/ethereum/c-kzg-4844 v1.0.2 h1:8tV84BCEiPeOkiVgW9mpYBeBUir2bkCNVqxPwwVeO+s=
github.com/ethereum/c-kzg-4844 v1.0.2/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA=
github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -176,8 +175,8 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4=
github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E=
github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk=
github.com/iden3/go-iden3-crypto v0.0.16/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
@@ -309,10 +308,12 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea h1:CH1WXWrpEpLaP3N+bFs2a1xdE0+lRm1AuJQb5YvE6Ls=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea/go.mod h1:i4VBgWoaW/y0D8MmQb7hSOulyw1dKhuiSFAbznwivCA=
github.com/scroll-tech/zktrie v0.8.2 h1:UMuIfA+jdgWMLmTgTL64Emo+zzMOdcnH0+eYdDcshxQ=
github.com/scroll-tech/zktrie v0.8.2/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/scroll-tech/da-codec v0.0.0-20240718144756-1875fd490923 h1:QKgfS8G0btzg7nmFjSjllaxGkns3yg7g2/tG1nWExEI=
github.com/scroll-tech/da-codec v0.0.0-20240718144756-1875fd490923/go.mod h1:D6XEESeNVJkQJlv3eK+FyR+ufPkgVQbJzERylQi53Bs=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240626125436-418bc6f728b6 h1:Q8YyvrcPIcXQwE4ucm4bqmPh6TP6IB1GUTXripf2WyQ=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240626125436-418bc6f728b6/go.mod h1:byf/mZ8jLYUCnUePTicjJWn+RvKdxDn7buS6glTnMwQ=
github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE=
github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec=
@@ -339,14 +340,14 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/supranational/blst v0.3.12 h1:Vfas2U2CFHhniv2QkUm2OVa1+pGTdqtpqm9NnhUUbZ8=
github.com/supranational/blst v0.3.12/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
@@ -369,8 +370,8 @@ github.com/ydb-platform/ydb-go-genproto v0.0.0-20231012155159-f85a672542fd h1:dz
github.com/ydb-platform/ydb-go-genproto v0.0.0-20231012155159-f85a672542fd/go.mod h1:Er+FePu1dNUieD+XTMDduGpQuCPssK5Q4BjF+IIXJ3I=
github.com/ydb-platform/ydb-go-sdk/v3 v3.54.2 h1:E0yUuuX7UmPxXm92+yQCjMveLFO3zfvYFIJVuAqsVRA=
github.com/ydb-platform/ydb-go-sdk/v3 v3.54.2/go.mod h1:fjBLQ2TdQNl4bMjuWl9adoTGBypwUTPoGC+EqYqiIcU=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
@@ -383,21 +384,21 @@ golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -414,20 +415,18 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE=

View File

@@ -141,7 +141,7 @@ func (c *L2MessageFetcher) fetchAndSaveEvents(confirmation uint64) {
return
}
if updateErr := c.eventUpdateLogic.UpdateL1BatchIndexAndStatus(c.ctx, c.l2SyncHeight); updateErr != nil {
if updateErr := c.eventUpdateLogic.UpdateL2WithdrawMessageProofs(c.ctx, c.l2SyncHeight); updateErr != nil {
log.Error("failed to update L1 batch index and status", "from", from, "to", to, "err", updateErr)
return
}

View File

@@ -125,6 +125,11 @@ func (b *EventUpdateLogic) L1InsertOrUpdate(ctx context.Context, l1FetcherResult
}
func (b *EventUpdateLogic) updateL2WithdrawMessageInfos(ctx context.Context, batchIndex, startBlock, endBlock uint64) error {
if startBlock > endBlock {
log.Warn("start block is greater than end block", "start", startBlock, "end", endBlock)
return nil
}
l2WithdrawMessages, err := b.crossMessageOrm.GetL2WithdrawalsByBlockRange(ctx, startBlock, endBlock)
if err != nil {
log.Error("failed to get L2 withdrawals by batch index", "batch index", batchIndex, "err", err)
@@ -147,7 +152,7 @@ func (b *EventUpdateLogic) updateL2WithdrawMessageInfos(ctx context.Context, bat
}
if withdrawTrie.NextMessageNonce != l2WithdrawMessages[0].MessageNonce {
log.Error("nonce mismatch", "expected next message nonce", withdrawTrie.NextMessageNonce, "actuall next message nonce", l2WithdrawMessages[0].MessageNonce)
log.Error("nonce mismatch", "expected next message nonce", withdrawTrie.NextMessageNonce, "actual next message nonce", l2WithdrawMessages[0].MessageNonce)
return fmt.Errorf("nonce mismatch")
}
@@ -173,24 +178,42 @@ func (b *EventUpdateLogic) updateL2WithdrawMessageInfos(ctx context.Context, bat
return nil
}
// UpdateL1BatchIndexAndStatus updates L1 finalized batch index and status
func (b *EventUpdateLogic) UpdateL1BatchIndexAndStatus(ctx context.Context, height uint64) error {
finalizedBatches, err := b.batchEventOrm.GetFinalizedBatchesLEBlockHeight(ctx, height)
// UpdateL2WithdrawMessageProofs updates L2 withdrawal message proofs.
func (b *EventUpdateLogic) UpdateL2WithdrawMessageProofs(ctx context.Context, height uint64) error {
lastUpdatedFinalizedBlockHeight, err := b.batchEventOrm.GetLastUpdatedFinalizedBlockHeight(ctx)
if err != nil {
log.Error("failed to get batches >= block height", "error", err)
log.Error("failed to get last updated finalized block height", "error", err)
return err
}
finalizedBatches, err := b.batchEventOrm.GetUnupdatedFinalizedBatchesLEBlockHeight(ctx, height)
if err != nil {
log.Error("failed to get unupdated finalized batches >= block height", "error", err)
return err
}
for _, finalizedBatch := range finalizedBatches {
log.Info("update finalized batch info of L2 withdrawals", "index", finalizedBatch.BatchIndex, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber)
if updateErr := b.updateL2WithdrawMessageInfos(ctx, finalizedBatch.BatchIndex, finalizedBatch.StartBlockNumber, finalizedBatch.EndBlockNumber); updateErr != nil {
log.Error("failed to update L2 withdraw message infos", "index", finalizedBatch.BatchIndex, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber, "error", updateErr)
log.Info("update finalized batch or bundle info of L2 withdrawals", "index", finalizedBatch.BatchIndex, "lastUpdatedFinalizedBlockHeight", lastUpdatedFinalizedBlockHeight, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber)
// This method is compatible with both "finalize by batch" and "finalize by bundle" modes:
// - In "finalize by batch" mode, each batch emits a FinalizedBatch event.
// - In "finalize by bundle" mode, all batches in the bundle emit only one FinalizedBatch event, using the last batch's index and hash.
//
// The method updates two types of information in L2 withdrawal messages:
// 1. Withdraw proof generation:
// - finalize by batch: Generates proofs for each batch.
// - finalize by bundle: Generates proofs for the entire bundle at once.
// 2. Batch index updating:
// - finalize by batch: Updates the batch index for withdrawal messages in each processed batch.
// - finalize by bundle: Updates the batch index for all withdrawal messages in the bundle, using the index of the last batch in the bundle.
if updateErr := b.updateL2WithdrawMessageInfos(ctx, finalizedBatch.BatchIndex, lastUpdatedFinalizedBlockHeight+1, finalizedBatch.EndBlockNumber); updateErr != nil {
log.Error("failed to update L2 withdraw message infos", "index", finalizedBatch.BatchIndex, "lastUpdatedFinalizedBlockHeight", lastUpdatedFinalizedBlockHeight, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber, "error", updateErr)
return updateErr
}
if dbErr := b.batchEventOrm.UpdateBatchEventStatus(ctx, finalizedBatch.BatchIndex); dbErr != nil {
log.Error("failed to update batch event status as updated", "index", finalizedBatch.BatchIndex, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber, "error", dbErr)
log.Error("failed to update batch event status as updated", "index", finalizedBatch.BatchIndex, "lastUpdatedFinalizedBlockHeight", lastUpdatedFinalizedBlockHeight, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber, "error", dbErr)
return dbErr
}
lastUpdatedFinalizedBlockHeight = finalizedBatch.EndBlockNumber
b.eventUpdateLogicL1FinalizeBatchEventL2BlockUpdateHeight.Set(float64(finalizedBatch.EndBlockNumber))
}
return nil

View File

@@ -407,7 +407,7 @@ func (h *HistoryLogic) cacheTxsInfo(ctx context.Context, cacheKey string, txs []
return err
}
} else {
// The transactions are sorted, thus we set the score as their indices.
// The transactions are sorted, thus we set the score as their index.
for _, tx := range txs {
txBytes, err := json.Marshal(tx)
if err != nil {

View File

@@ -53,8 +53,26 @@ func (c *BatchEvent) GetBatchEventSyncedHeightInDB(ctx context.Context) (uint64,
return batch.L1BlockNumber, nil
}
// GetFinalizedBatchesLEBlockHeight returns the finalized batches with end block <= given block height in db.
func (c *BatchEvent) GetFinalizedBatchesLEBlockHeight(ctx context.Context, blockHeight uint64) ([]*BatchEvent, error) {
// GetLastUpdatedFinalizedBlockHeight returns the last updated finalized block height in db.
func (c *BatchEvent) GetLastUpdatedFinalizedBlockHeight(ctx context.Context) (uint64, error) {
var batch BatchEvent
db := c.db.WithContext(ctx)
db = db.Model(&BatchEvent{})
db = db.Where("batch_status = ?", btypes.BatchStatusTypeFinalized)
db = db.Where("update_status = ?", btypes.UpdateStatusTypeUpdated)
db = db.Order("batch_index desc")
if err := db.First(&batch).Error; err != nil {
if err == gorm.ErrRecordNotFound {
// No finalized batch found, return genesis batch's end block number.
return 0, nil
}
return 0, fmt.Errorf("failed to get last updated finalized block height, error: %w", err)
}
return batch.EndBlockNumber, nil
}
// GetUnupdatedFinalizedBatchesLEBlockHeight returns the finalized batches with end block <= given block height in db.
func (c *BatchEvent) GetUnupdatedFinalizedBatchesLEBlockHeight(ctx context.Context, blockHeight uint64) ([]*BatchEvent, error) {
var batches []*BatchEvent
db := c.db.WithContext(ctx)
db = db.Model(&BatchEvent{})
@@ -66,7 +84,7 @@ func (c *BatchEvent) GetFinalizedBatchesLEBlockHeight(ctx context.Context, block
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, fmt.Errorf("failed to get batches >= block height, error: %w", err)
return nil, fmt.Errorf("failed to get unupdated finalized batches >= block height, error: %w", err)
}
return batches, nil
}
@@ -92,6 +110,7 @@ func (c *BatchEvent) InsertOrUpdateBatchEvents(ctx context.Context, l1BatchEvent
db = db.Where("batch_index = ?", l1BatchEvent.BatchIndex)
db = db.Where("batch_hash = ?", l1BatchEvent.BatchHash)
updateFields["batch_status"] = btypes.BatchStatusTypeFinalized
updateFields["l1_block_number"] = l1BatchEvent.L1BlockNumber
if err := db.Updates(updateFields).Error; err != nil {
return fmt.Errorf("failed to update batch event, error: %w", err)
}

View File

@@ -66,32 +66,55 @@ func ComputeMessageHash(
return common.BytesToHash(crypto.Keccak256(data))
}
type commitBatchArgs struct {
Version uint8
ParentBatchHeader []byte
Chunks [][]byte
SkippedL1MessageBitmap []byte
}
// GetBatchRangeFromCalldata find the block range from calldata, both inclusive.
func GetBatchRangeFromCalldata(calldata []byte) (uint64, uint64, error) {
method := backendabi.IScrollChainABI.Methods["commitBatch"]
values, err := method.Inputs.Unpack(calldata[4:])
if err != nil {
// special case: import genesis batch
method = backendabi.IScrollChainABI.Methods["importGenesisBatch"]
_, err2 := method.Inputs.Unpack(calldata[4:])
if err2 == nil {
// genesis batch
return 0, 0, nil
}
// none of "commitBatch" and "importGenesisBatch" match, give up
return 0, 0, err
func GetBatchRangeFromCalldata(txData []byte) (uint64, uint64, error) {
const methodIDLength = 4
if len(txData) < methodIDLength {
return 0, 0, fmt.Errorf("transaction data is too short, length of tx data: %v, minimum length required: %v", len(txData), methodIDLength)
}
args := commitBatchArgs{}
err = method.Inputs.Copy(&args, values)
method, err := backendabi.IScrollChainABI.MethodById(txData[:methodIDLength])
if err != nil {
return 0, 0, err
return 0, 0, fmt.Errorf("failed to get method by ID, ID: %v, err: %w", txData[:methodIDLength], err)
}
values, err := method.Inputs.Unpack(txData[methodIDLength:])
if err != nil {
return 0, 0, fmt.Errorf("failed to unpack transaction data using ABI, tx data: %v, err: %w", txData, err)
}
var chunks [][]byte
if method.Name == "importGenesisBatch" {
return 0, 0, nil
} else if method.Name == "commitBatch" {
type commitBatchArgs struct {
Version uint8
ParentBatchHeader []byte
Chunks [][]byte
SkippedL1MessageBitmap []byte
}
var args commitBatchArgs
if err = method.Inputs.Copy(&args, values); err != nil {
return 0, 0, fmt.Errorf("failed to decode calldata into commitBatch args, values: %+v, err: %w", values, err)
}
chunks = args.Chunks
} else if method.Name == "commitBatchWithBlobProof" {
type commitBatchWithBlobProofArgs struct {
Version uint8
ParentBatchHeader []byte
Chunks [][]byte
SkippedL1MessageBitmap []byte
BlobDataProof []byte
}
var args commitBatchWithBlobProofArgs
if err = method.Inputs.Copy(&args, values); err != nil {
return 0, 0, fmt.Errorf("failed to decode calldata into commitBatchWithBlobProofArgs args, values: %+v, err: %w", values, err)
}
chunks = args.Chunks
}
var startBlock uint64
@@ -100,14 +123,14 @@ func GetBatchRangeFromCalldata(calldata []byte) (uint64, uint64, error) {
// decode blocks from chunk and assume that there's no empty chunk
// | 1 byte | 60 bytes | ... | 60 bytes |
// | num blocks | block 1 | ... | block n |
if len(args.Chunks) == 0 {
if len(chunks) == 0 {
return 0, 0, errors.New("invalid chunks")
}
chunk := args.Chunks[0]
chunk := chunks[0]
block := chunk[1:61] // first block in chunk
startBlock = binary.BigEndian.Uint64(block[0:8])
chunk = args.Chunks[len(args.Chunks)-1]
chunk = chunks[len(chunks)-1]
lastBlockIndex := int(chunk[0]) - 1
block = chunk[1+lastBlockIndex*60 : 1+lastBlockIndex*60+60] // last block in chunk
finishBlock = binary.BigEndian.Uint64(block[0:8])

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM golang:1.21-alpine3.19 as base
FROM scrolltech/go-rust-builder:go-1.21-rust-nightly-2023-12-03 as base
WORKDIR /src
COPY go.mod* ./
@@ -11,11 +11,13 @@ FROM base as builder
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/bridge-history-api/cmd/api && go build -v -p 4 -o /bin/bridgehistoryapi-api
cd /src/bridge-history-api/cmd/api && CGO_LDFLAGS="-Wl,--no-as-needed -ldl" go build -v -p 4 -o /bin/bridgehistoryapi-api
# Pull bridgehistoryapi-api into a second stage deploy alpine container
FROM alpine:latest
# Pull bridgehistoryapi-api into a second stage deploy ubuntu container
FROM ubuntu:20.04
ENV CGO_LDFLAGS="-Wl,--no-as-needed -ldl"
COPY --from=builder /bin/bridgehistoryapi-api /bin/
WORKDIR /app
ENTRYPOINT ["bridgehistoryapi-api"]
ENTRYPOINT ["bridgehistoryapi-api"]

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM golang:1.21-alpine3.19 as base
FROM scrolltech/go-rust-builder:go-1.21-rust-nightly-2023-12-03 as base
WORKDIR /src
COPY go.mod* ./
@@ -11,11 +11,13 @@ FROM base as builder
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/bridge-history-api/cmd/fetcher && go build -v -p 4 -o /bin/bridgehistoryapi-fetcher
cd /src/bridge-history-api/cmd/fetcher && CGO_LDFLAGS="-Wl,--no-as-needed -ldl" go build -v -p 4 -o /bin/bridgehistoryapi-fetcher
# Pull bridgehistoryapi-fetcher into a second stage deploy alpine container
FROM alpine:latest
# Pull bridgehistoryapi-fetcher into a second stage deploy ubuntu container
FROM ubuntu:20.04
ENV CGO_LDFLAGS="-Wl,--no-as-needed -ldl"
COPY --from=builder /bin/bridgehistoryapi-fetcher /bin/
WORKDIR /app
ENTRYPOINT ["bridgehistoryapi-fetcher"]
ENTRYPOINT ["bridgehistoryapi-fetcher"]

View File

@@ -23,7 +23,6 @@ COPY ./rollup/go.* ./rollup/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
RUN go mod download -x
@@ -34,11 +33,12 @@ FROM base as builder
COPY . .
RUN cp -r ./common/libzkp/interface ./coordinator/internal/logic/verifier/lib
COPY --from=zkp-builder /app/target/release/libzkp.so ./coordinator/internal/logic/verifier/lib/
RUN cd ./coordinator && make coordinator_api_skip_libzkp && mv ./build/bin/coordinator_api /bin/coordinator_api && mv internal/logic/verifier/lib /bin/
RUN cd ./coordinator && CGO_LDFLAGS="-Wl,--no-as-needed -ldl" make coordinator_api_skip_libzkp && mv ./build/bin/coordinator_api /bin/coordinator_api && mv internal/logic/verifier/lib /bin/
# Pull coordinator into a second stage deploy alpine container
# Pull coordinator into a second stage deploy ubuntu container
FROM ubuntu:20.04
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/src/coordinator/internal/logic/verifier/lib
ENV CGO_LDFLAGS="-Wl,--no-as-needed -ldl"
# ENV CHAIN_ID=534353
RUN mkdir -p /src/coordinator/internal/logic/verifier/lib
COPY --from=builder /bin/lib /src/coordinator/internal/logic/verifier/lib

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.21 as base
FROM scrolltech/go-rust-builder:go-1.21-rust-nightly-2023-12-03 as base
WORKDIR /src
COPY go.work* ./
@@ -7,7 +7,6 @@ COPY ./rollup/go.* ./rollup/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
RUN go mod download -x
@@ -16,10 +15,13 @@ RUN go mod download -x
FROM base as builder
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/coordinator/cmd/cron/ && go build -v -p 4 -o /bin/coordinator_cron
cd /src/coordinator/cmd/cron/ && CGO_LDFLAGS="-Wl,--no-as-needed -ldl" go build -v -p 4 -o /bin/coordinator_cron
# Pull coordinator into a second stage deploy ubuntu container
FROM ubuntu:20.04
ENV CGO_LDFLAGS="-Wl,--no-as-needed -ldl"
# Pull coordinator into a second stage deploy alpine container
FROM alpine:latest
COPY --from=builder /bin/coordinator_cron /bin/
WORKDIR /app
ENTRYPOINT ["coordinator_cron"]
ENTRYPOINT ["coordinator_cron"]

View File

@@ -7,7 +7,6 @@ COPY ./rollup/go.* ./rollup/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
RUN go mod download -x

View File

@@ -1,29 +0,0 @@
# Download Go dependencies
FROM scrolltech/go-rust-builder:go-1.21-rust-nightly-2023-12-03 as base
WORKDIR /src
COPY go.work* ./
COPY ./rollup/go.* ./rollup/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
RUN go mod download -x
# Build event_watcher
FROM base as builder
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/rollup/cmd/event_watcher/ && CGO_LDFLAGS="-ldl" go build -v -p 4 -o /bin/event_watcher
# Pull event_watcher into a second stage deploy alpine container
FROM ubuntu:20.04
ENV CGO_LDFLAGS="-ldl"
COPY --from=builder /bin/event_watcher /bin/
WORKDIR /app
ENTRYPOINT ["event_watcher"]

View File

@@ -1,5 +0,0 @@
assets/
docs/
l2geth/
rpc-gateway/
*target/*

View File

@@ -7,7 +7,6 @@ COPY ./rollup/go.* ./rollup/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
RUN go mod download -x
@@ -19,11 +18,13 @@ RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/rollup/cmd/gas_oracle/ && CGO_LDFLAGS="-ldl" go build -v -p 4 -o /bin/gas_oracle
# Pull gas_oracle into a second stage deploy alpine container
# Pull gas_oracle into a second stage deploy ubuntu container
FROM ubuntu:20.04
RUN apt update && apt install ca-certificates -y
ENV CGO_LDFLAGS="-ldl"
COPY --from=builder /bin/gas_oracle /bin/
WORKDIR /app
ENTRYPOINT ["gas_oracle"]
ENTRYPOINT ["gas_oracle"]

View File

@@ -7,7 +7,6 @@ COPY ./rollup/go.* ./rollup/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
RUN go mod download -x
@@ -19,9 +18,11 @@ RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/rollup/cmd/rollup_relayer/ && CGO_LDFLAGS="-ldl" go build -v -p 4 -o /bin/rollup_relayer
# Pull rollup_relayer into a second stage deploy alpine container
# Pull rollup_relayer into a second stage deploy ubuntu container
FROM ubuntu:20.04
RUN apt update && apt install ca-certificates -y
ENV CGO_LDFLAGS="-ldl"
COPY --from=builder /bin/rollup_relayer /bin/

View File

@@ -5,6 +5,7 @@ import (
"math/big"
"sort"
"github.com/scroll-tech/da-codec/encoding"
"github.com/scroll-tech/go-ethereum/params"
)
@@ -63,17 +64,6 @@ func CollectSortedForkHeights(config *params.ChainConfig) ([]uint64, map[uint64]
return forkHeights, forkHeightsMap, forkNameHeightMap
}
// BlocksUntilFork returns the number of blocks until the next fork
// returns 0 if there is no fork scheduled for the future
func BlocksUntilFork(blockHeight uint64, forkHeights []uint64) uint64 {
for _, forkHeight := range forkHeights {
if forkHeight > blockHeight {
return forkHeight - blockHeight
}
}
return 0
}
// BlockRange returns the block range of the hard fork
// Need ensure the forkHeights is incremental
func BlockRange(currentForkHeight uint64, forkHeights []uint64) (from, to uint64) {
@@ -87,3 +77,45 @@ func BlockRange(currentForkHeight uint64, forkHeights []uint64) (from, to uint64
}
return
}
// GetHardforkName returns the name of the hardfork active at the given block height and timestamp.
// It checks the chain configuration to determine which hardfork is active.
func GetHardforkName(config *params.ChainConfig, blockHeight, blockTimestamp uint64) string {
if !config.IsBernoulli(new(big.Int).SetUint64(blockHeight)) {
return "homestead"
} else if !config.IsCurie(new(big.Int).SetUint64(blockHeight)) {
return "bernoulli"
} else if !config.IsDarwin(blockTimestamp) {
return "curie"
} else {
return "darwin"
}
}
// GetCodecVersion returns the encoding codec version for the given block height and timestamp.
// It determines the appropriate codec version based on the active hardfork.
func GetCodecVersion(config *params.ChainConfig, blockHeight, blockTimestamp uint64) encoding.CodecVersion {
if !config.IsBernoulli(new(big.Int).SetUint64(blockHeight)) {
return encoding.CodecV0
} else if !config.IsCurie(new(big.Int).SetUint64(blockHeight)) {
return encoding.CodecV1
} else if !config.IsDarwin(blockTimestamp) {
return encoding.CodecV2
} else {
return encoding.CodecV3
}
}
// GetMaxChunksPerBatch returns the maximum number of chunks allowed per batch for the given block height and timestamp.
// This value may change depending on the active hardfork.
func GetMaxChunksPerBatch(config *params.ChainConfig, blockHeight, blockTimestamp uint64) uint64 {
if !config.IsBernoulli(new(big.Int).SetUint64(blockHeight)) {
return 15
} else if !config.IsCurie(new(big.Int).SetUint64(blockHeight)) {
return 15
} else if !config.IsDarwin(blockTimestamp) {
return 45
} else {
return 45
}
}

View File

@@ -33,46 +33,6 @@ func TestCollectSortedForkBlocks(t *testing.T) {
}, n)
}
func TestBlocksUntilFork(t *testing.T) {
tests := map[string]struct {
block uint64
forks []uint64
expected uint64
}{
"NoFork": {
block: 44,
forks: []uint64{},
expected: 0,
},
"BeforeFork": {
block: 0,
forks: []uint64{1, 5},
expected: 1,
},
"OnFork": {
block: 1,
forks: []uint64{1, 5},
expected: 4,
},
"OnLastFork": {
block: 5,
forks: []uint64{1, 5},
expected: 0,
},
"AfterFork": {
block: 5,
forks: []uint64{1, 5},
expected: 0,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
require.Equal(t, test.expected, BlocksUntilFork(test.block, test.forks))
})
}
}
func TestBlockRange(t *testing.T) {
tests := []struct {
name string

View File

@@ -4,7 +4,7 @@ go 1.21
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/bits-and-blooms/bitset v1.12.0
github.com/bits-and-blooms/bitset v1.13.0
github.com/docker/docker v26.1.0+incompatible
github.com/gin-contrib/pprof v1.4.0
github.com/gin-gonic/gin v1.9.1
@@ -13,7 +13,8 @@ require (
github.com/modern-go/reflect2 v1.0.2
github.com/orcaman/concurrent-map v1.0.0
github.com/prometheus/client_golang v1.19.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea
github.com/scroll-tech/da-codec v0.0.0-20240718144756-1875fd490923
github.com/scroll-tech/go-ethereum v1.10.14-0.20240626125436-418bc6f728b6
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.30.0
github.com/testcontainers/testcontainers-go/modules/compose v0.30.0
@@ -77,7 +78,7 @@ require (
github.com/docker/go-units v0.5.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 // indirect
github.com/ethereum/c-kzg-4844 v1.0.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fjl/memsize v0.0.2 // indirect
github.com/fsnotify/fsevents v0.1.1 // indirect
@@ -119,7 +120,7 @@ require (
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/iden3/go-iden3-crypto v0.0.15 // indirect
github.com/iden3/go-iden3-crypto v0.0.16 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/in-toto/in-toto-golang v0.5.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -182,7 +183,7 @@ require (
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/scroll-tech/zktrie v0.8.2 // indirect
github.com/scroll-tech/zktrie v0.8.4 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
@@ -194,12 +195,12 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.4.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/supranational/blst v0.3.12 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/theupdateframework/notary v0.7.0 // indirect
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/tonistiigi/fsutil v0.0.0-20230825212630-f09800878302 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 // indirect
@@ -210,7 +211,7 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.45.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
@@ -229,17 +230,17 @@ require (
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.17.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect

View File

@@ -70,8 +70,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bits-and-blooms/bitset v1.12.0 h1:U/q1fAF7xXRhFCrhROzIfffYnu+dlS38vCZtmFVPHmA=
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
@@ -212,8 +212,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c=
github.com/ethereum/c-kzg-4844 v1.0.2 h1:8tV84BCEiPeOkiVgW9mpYBeBUir2bkCNVqxPwwVeO+s=
github.com/ethereum/c-kzg-4844 v1.0.2/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA=
@@ -384,8 +384,8 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4=
github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E=
github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk=
github.com/iden3/go-iden3-crypto v0.0.16/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY=
@@ -633,10 +633,12 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea h1:CH1WXWrpEpLaP3N+bFs2a1xdE0+lRm1AuJQb5YvE6Ls=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea/go.mod h1:i4VBgWoaW/y0D8MmQb7hSOulyw1dKhuiSFAbznwivCA=
github.com/scroll-tech/zktrie v0.8.2 h1:UMuIfA+jdgWMLmTgTL64Emo+zzMOdcnH0+eYdDcshxQ=
github.com/scroll-tech/zktrie v0.8.2/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/scroll-tech/da-codec v0.0.0-20240718144756-1875fd490923 h1:QKgfS8G0btzg7nmFjSjllaxGkns3yg7g2/tG1nWExEI=
github.com/scroll-tech/da-codec v0.0.0-20240718144756-1875fd490923/go.mod h1:D6XEESeNVJkQJlv3eK+FyR+ufPkgVQbJzERylQi53Bs=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240626125436-418bc6f728b6 h1:Q8YyvrcPIcXQwE4ucm4bqmPh6TP6IB1GUTXripf2WyQ=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240626125436-418bc6f728b6/go.mod h1:byf/mZ8jLYUCnUePTicjJWn+RvKdxDn7buS6glTnMwQ=
github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE=
github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs=
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ=
@@ -700,8 +702,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/supranational/blst v0.3.12 h1:Vfas2U2CFHhniv2QkUm2OVa1+pGTdqtpqm9NnhUUbZ8=
github.com/supranational/blst v0.3.12/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/testcontainers/testcontainers-go v0.30.0 h1:jmn/XS22q4YRrcMwWg0pAwlClzs/abopbsBzrepyc4E=
@@ -714,10 +716,12 @@ github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4D
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA=
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tonistiigi/fsutil v0.0.0-20230825212630-f09800878302 h1:ZT8ibgassurSISJ1Pj26NsM3vY2jxFZn63Nd/TpHmRw=
github.com/tonistiigi/fsutil v0.0.0-20230825212630-f09800878302/go.mod h1:9kMVqMyQ/Sx2df5LtnGG+nbrmiZzCS7V6gjW3oGHsvI=
@@ -754,8 +758,9 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300 h1:DZH5n7L3L8RxKdSyJHZt7WePgwdhHnPhQFdQSJaHF+o=
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300/go.mod h1:mOd4yUMgn2fe2nV9KXsa9AyQBFZGzygVPovsZR+Rl5w=
github.com/zmap/zlint/v3 v3.5.0 h1:Eh2B5t6VKgVH0DFmTwOqE50POvyDhUaU9T2mJOe1vfQ=
@@ -815,8 +820,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
@@ -826,8 +831,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -846,8 +851,8 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
@@ -859,8 +864,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -901,21 +906,21 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -930,8 +935,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -31,7 +31,7 @@ dependencies = [
[[package]]
name = "aggregator"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"ark-std 0.3.0",
"bitstream-io",
@@ -39,9 +39,9 @@ dependencies = [
"ctor",
"encoder",
"env_logger 0.10.0",
"eth-types",
"eth-types 0.11.0",
"ethers-core",
"gadgets",
"gadgets 0.11.0",
"halo2-base",
"halo2-ecc",
"halo2_proofs",
@@ -59,7 +59,41 @@ dependencies = [
"snark-verifier-sdk",
"strum 0.25.0",
"strum_macros 0.25.3",
"zkevm-circuits",
"zkevm-circuits 0.11.0",
]
[[package]]
name = "aggregator"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"ark-std 0.3.0",
"bitstream-io",
"c-kzg",
"ctor",
"encoder",
"env_logger 0.10.0",
"eth-types 0.12.0",
"ethers-core",
"gadgets 0.12.0",
"halo2-base",
"halo2-ecc",
"halo2_proofs",
"hex",
"itertools 0.11.0",
"log",
"num-bigint",
"once_cell",
"rand",
"revm-precompile",
"revm-primitives",
"serde",
"serde_json",
"snark-verifier",
"snark-verifier-sdk",
"strum 0.25.0",
"strum_macros 0.25.3",
"zkevm-circuits 0.12.0",
]
[[package]]
@@ -537,20 +571,20 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "bus-mapping"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"eth-types",
"eth-types 0.11.0",
"ethers-core",
"ethers-providers",
"ethers-signers",
"external-tracer",
"gadgets",
"external-tracer 0.11.0",
"gadgets 0.11.0",
"halo2_proofs",
"hex",
"itertools 0.11.0",
"log",
"mock",
"mpt-zktrie",
"mock 0.11.0",
"mpt-zktrie 0.11.0",
"num",
"poseidon-circuit",
"rand",
@@ -561,6 +595,31 @@ dependencies = [
"strum_macros 0.25.3",
]
[[package]]
name = "bus-mapping"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"eth-types 0.12.0",
"ethers-core",
"ethers-providers",
"ethers-signers",
"gadgets 0.12.0",
"halo2_proofs",
"hex",
"itertools 0.11.0",
"log",
"mock 0.12.0",
"mpt-zktrie 0.12.0",
"num",
"poseidon-circuit",
"revm-precompile",
"serde",
"serde_json",
"strum 0.25.0",
"strum_macros 0.25.3",
]
[[package]]
name = "byte-slice-cast"
version = "1.2.2"
@@ -1126,7 +1185,7 @@ dependencies = [
[[package]]
name = "eth-types"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"base64 0.13.1",
"ethers-core",
@@ -1152,6 +1211,34 @@ dependencies = [
"uint",
]
[[package]]
name = "eth-types"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"base64 0.13.1",
"ethers-core",
"ethers-signers",
"halo2curves",
"hex",
"itertools 0.11.0",
"log",
"num",
"num-bigint",
"poseidon-base",
"regex",
"revm-precompile",
"revm-primitives",
"serde",
"serde_json",
"serde_with",
"sha3 0.10.8",
"strum 0.25.0",
"strum_macros 0.25.3",
"subtle",
"uint",
]
[[package]]
name = "ethabi"
version = "18.0.0"
@@ -1283,10 +1370,23 @@ dependencies = [
[[package]]
name = "external-tracer"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"eth-types",
"geth-utils",
"eth-types 0.11.0",
"geth-utils 0.11.0",
"log",
"serde",
"serde_json",
"serde_stacker",
]
[[package]]
name = "external-tracer"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"eth-types 0.12.0",
"geth-utils 0.12.0",
"log",
"serde",
"serde_json",
@@ -1465,9 +1565,21 @@ dependencies = [
[[package]]
name = "gadgets"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"eth-types",
"eth-types 0.11.0",
"halo2_proofs",
"poseidon-base",
"sha3 0.10.8",
"strum 0.25.0",
]
[[package]]
name = "gadgets"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"eth-types 0.12.0",
"halo2_proofs",
"poseidon-base",
"sha3 0.10.8",
@@ -1488,7 +1600,17 @@ dependencies = [
[[package]]
name = "geth-utils"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"env_logger 0.10.0",
"gobuild",
"log",
]
[[package]]
name = "geth-utils"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"env_logger 0.10.0",
"gobuild",
@@ -2237,12 +2359,27 @@ dependencies = [
[[package]]
name = "mock"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"eth-types",
"eth-types 0.11.0",
"ethers-core",
"ethers-signers",
"external-tracer",
"external-tracer 0.11.0",
"itertools 0.11.0",
"log",
"rand",
"rand_chacha",
]
[[package]]
name = "mock"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"eth-types 0.12.0",
"ethers-core",
"ethers-signers",
"external-tracer 0.12.0",
"itertools 0.11.0",
"log",
"rand",
@@ -2252,9 +2389,23 @@ dependencies = [
[[package]]
name = "mpt-zktrie"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"eth-types",
"eth-types 0.11.0",
"halo2curves",
"hex",
"log",
"num-bigint",
"poseidon-base",
"zktrie",
]
[[package]]
name = "mpt-zktrie"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"eth-types 0.12.0",
"halo2curves",
"hex",
"log",
@@ -2724,16 +2875,16 @@ dependencies = [
[[package]]
name = "prover"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"aggregator",
"aggregator 0.11.0",
"anyhow",
"base64 0.13.1",
"blake2",
"bus-mapping",
"bus-mapping 0.11.0",
"chrono",
"dotenvy",
"eth-types",
"eth-types 0.11.0",
"ethers-core",
"git-version",
"halo2_proofs",
@@ -2741,7 +2892,7 @@ dependencies = [
"itertools 0.11.0",
"log",
"log4rs",
"mpt-zktrie",
"mpt-zktrie 0.11.0",
"num-bigint",
"rand",
"rand_xorshift",
@@ -2752,7 +2903,41 @@ dependencies = [
"sha2",
"snark-verifier",
"snark-verifier-sdk",
"zkevm-circuits",
"zkevm-circuits 0.11.0",
]
[[package]]
name = "prover"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"aggregator 0.12.0",
"anyhow",
"base64 0.13.1",
"blake2",
"bus-mapping 0.12.0",
"chrono",
"dotenvy",
"eth-types 0.12.0",
"ethers-core",
"git-version",
"halo2_proofs",
"hex",
"itertools 0.11.0",
"log",
"log4rs",
"mpt-zktrie 0.12.0",
"num-bigint",
"rand",
"rand_xorshift",
"serde",
"serde_derive",
"serde_json",
"serde_stacker",
"sha2",
"snark-verifier",
"snark-verifier-sdk",
"zkevm-circuits 0.12.0",
]
[[package]]
@@ -2958,7 +3143,7 @@ dependencies = [
[[package]]
name = "revm-precompile"
version = "7.0.0"
source = "git+https://github.com/scroll-tech/revm?branch=scroll-evm-executor/v36#8543dd627348907773d8057807b6a310b276bb30"
source = "git+https://github.com/scroll-tech/revm?branch=scroll-evm-executor/v36#36c304d9e9ba4e4b2d5468d91a6bd27210133b6a"
dependencies = [
"aurora-engine-modexp",
"c-kzg",
@@ -2974,7 +3159,7 @@ dependencies = [
[[package]]
name = "revm-primitives"
version = "4.0.0"
source = "git+https://github.com/scroll-tech/revm?branch=scroll-evm-executor/v36#8543dd627348907773d8057807b6a310b276bb30"
source = "git+https://github.com/scroll-tech/revm?branch=scroll-evm-executor/v36#36c304d9e9ba4e4b2d5468d91a6bd27210133b6a"
dependencies = [
"alloy-primitives",
"auto_impl",
@@ -3525,7 +3710,7 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "snark-verifier"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#fe1f8906041ad323034881fbd808908250d44829"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#58c46b74c73156b9e09dc27617369d2acfb4461b"
dependencies = [
"bytes",
"ethereum-types",
@@ -3548,7 +3733,7 @@ dependencies = [
[[package]]
name = "snark-verifier-sdk"
version = "0.0.1"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#fe1f8906041ad323034881fbd808908250d44829"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#58c46b74c73156b9e09dc27617369d2acfb4461b"
dependencies = [
"bincode",
"ethereum-types",
@@ -4361,17 +4546,17 @@ dependencies = [
[[package]]
name = "zkevm-circuits"
version = "0.11.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.1#512996f1bac1218c93d9d3de49d7b86f52726c27"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.11.4#38a68e22d3d8449bd39a50c22da55b9e741de453"
dependencies = [
"array-init",
"bus-mapping",
"bus-mapping 0.11.0",
"either",
"env_logger 0.10.0",
"eth-types",
"eth-types 0.11.0",
"ethers-core",
"ethers-signers",
"ff",
"gadgets",
"gadgets 0.11.0",
"halo2-base",
"halo2-ecc",
"halo2-mpt-circuits",
@@ -4381,8 +4566,50 @@ dependencies = [
"itertools 0.11.0",
"log",
"misc-precompiled-circuit",
"mock",
"mpt-zktrie",
"mock 0.11.0",
"mpt-zktrie 0.11.0",
"num",
"num-bigint",
"poseidon-circuit",
"rand",
"rand_chacha",
"rand_xorshift",
"rayon",
"serde",
"serde_json",
"sha3 0.10.8",
"snark-verifier",
"snark-verifier-sdk",
"strum 0.25.0",
"strum_macros 0.25.3",
"subtle",
]
[[package]]
name = "zkevm-circuits"
version = "0.12.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.12.0-rc.3#706ba9ee7292b8e15a4fa0d4634a65dffa999402"
dependencies = [
"array-init",
"bus-mapping 0.12.0",
"either",
"env_logger 0.10.0",
"eth-types 0.12.0",
"ethers-core",
"ethers-signers",
"ff",
"gadgets 0.12.0",
"halo2-base",
"halo2-ecc",
"halo2-mpt-circuits",
"halo2_gadgets",
"halo2_proofs",
"hex",
"itertools 0.11.0",
"log",
"misc-precompiled-circuit",
"mock 0.12.0",
"mpt-zktrie 0.12.0",
"num",
"num-bigint",
"poseidon-circuit",
@@ -4410,7 +4637,8 @@ dependencies = [
"libc",
"log",
"once_cell",
"prover",
"prover 0.11.0",
"prover 0.12.0",
"serde",
"serde_derive",
"serde_json",

View File

@@ -25,7 +25,11 @@ bls12_381 = { git = "https://github.com/scroll-tech/bls12_381", branch = "feat/i
[dependencies]
halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "v1.1" }
snark-verifier-sdk = { git = "https://github.com/scroll-tech/snark-verifier", branch = "develop", default-features = false, features = ["loader_halo2", "loader_evm", "halo2-pse"] }
prover = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.11.1", default-features = false, features = ["parallel_syn", "scroll"] }
# curie
prover_v3 = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.11.4", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] }
# darwin
prover_v4 = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.12.0-rc.3", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] }
base64 = "0.13.0"
env_logger = "0.9.0"

View File

@@ -6,18 +6,20 @@ use crate::{
},
};
use libc::c_char;
use prover::{
aggregator::{Prover, Verifier},
use prover_v3::BatchProof as BatchProofV3;
use prover_v4::{
aggregator::{Prover, Verifier as VerifierV4},
check_chunk_hashes,
consts::AGG_VK_FILENAME,
consts::BATCH_VK_FILENAME,
utils::{chunk_trace_to_witness_block, init_env_and_log},
BatchProof, BatchProvingTask, BlockTrace, ChunkInfo, ChunkProof,
BatchHeader, BatchProof as BatchProofV4, BatchProvingTask, BlockTrace, BundleProof,
BundleProvingTask, ChunkInfo, ChunkProof, MAX_AGG_SNARKS,
};
use snark_verifier_sdk::verify_evm_calldata;
use std::{cell::OnceCell, env, ptr::null};
static mut PROVER: OnceCell<Prover> = OnceCell::new();
static mut VERIFIER: OnceCell<Verifier> = OnceCell::new();
static mut VERIFIER_V4: OnceCell<VerifierV4> = OnceCell::new();
/// # Safety
#[no_mangle]
@@ -31,8 +33,8 @@ pub unsafe extern "C" fn init_batch_prover(params_dir: *const c_char, assets_dir
env::set_var("SCROLL_PROVER_ASSETS_DIR", assets_dir);
// VK file must exist, it is optional and logged as a warning in prover.
if !file_exists(assets_dir, &AGG_VK_FILENAME) {
panic!("{} must exist in folder {}", *AGG_VK_FILENAME, assets_dir);
if !file_exists(assets_dir, &BATCH_VK_FILENAME) {
panic!("{} must exist in folder {}", *BATCH_VK_FILENAME, assets_dir);
}
let prover = Prover::from_dirs(params_dir, assets_dir);
@@ -50,15 +52,26 @@ pub unsafe extern "C" fn init_batch_verifier(params_dir: *const c_char, assets_d
// TODO: add a settings in scroll-prover.
env::set_var("SCROLL_PROVER_ASSETS_DIR", assets_dir);
let verifier = Verifier::from_dirs(params_dir, assets_dir);
let verifier_v4 = VerifierV4::from_dirs(params_dir, assets_dir);
VERIFIER.set(verifier).unwrap();
VERIFIER_V4.set(verifier_v4).unwrap();
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn get_batch_vk() -> *const c_char {
let vk_result = panic_catch(|| PROVER.get_mut().unwrap().get_vk());
let vk_result = panic_catch(|| PROVER.get_mut().unwrap().get_batch_vk());
vk_result
.ok()
.flatten()
.map_or(null(), |vk| string_to_c_char(base64::encode(vk)))
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn get_bundle_vk() -> *const c_char {
let vk_result = panic_catch(|| PROVER.get_mut().unwrap().get_bundle_vk());
vk_result
.ok()
@@ -104,15 +117,19 @@ pub unsafe extern "C" fn check_chunk_proofs(chunk_proofs: *const c_char) -> *con
pub unsafe extern "C" fn gen_batch_proof(
chunk_hashes: *const c_char,
chunk_proofs: *const c_char,
batch_header: *const c_char,
) -> *const c_char {
let proof_result: Result<Vec<u8>, String> = panic_catch(|| {
let chunk_hashes = c_char_to_vec(chunk_hashes);
let chunk_proofs = c_char_to_vec(chunk_proofs);
let batch_header = c_char_to_vec(batch_header);
let chunk_hashes = serde_json::from_slice::<Vec<ChunkInfo>>(&chunk_hashes)
.map_err(|e| format!("failed to deserialize chunk hashes: {e:?}"))?;
let chunk_proofs = serde_json::from_slice::<Vec<ChunkProof>>(&chunk_proofs)
.map_err(|e| format!("failed to deserialize chunk proofs: {e:?}"))?;
let batch_header = serde_json::from_slice::<BatchHeader<MAX_AGG_SNARKS>>(&batch_header)
.map_err(|e| format!("failed to deserialize batch header: {e:?}"))?;
if chunk_hashes.len() != chunk_proofs.len() {
return Err(format!("chunk hashes and chunk proofs lengths mismatch: chunk_hashes.len() = {}, chunk_proofs.len() = {}",
@@ -126,12 +143,13 @@ pub unsafe extern "C" fn gen_batch_proof(
check_chunk_hashes("", &chunk_hashes_proofs).map_err(|e| format!("failed to check chunk info: {e:?}"))?;
let batch = BatchProvingTask {
chunk_proofs
chunk_proofs,
batch_header,
};
let proof = PROVER
.get_mut()
.expect("failed to get mutable reference to PROVER.")
.gen_agg_evm_proof(batch, None, OUTPUT_DIR.as_deref())
.gen_batch_proof(batch, None, OUTPUT_DIR.as_deref())
.map_err(|e| format!("failed to generate proof: {e:?}"))?;
serde_json::to_vec(&proof).map_err(|e| format!("failed to serialize the proof: {e:?}"))
@@ -159,30 +177,76 @@ pub unsafe extern "C" fn verify_batch_proof(
fork_name: *const c_char,
) -> c_char {
let proof = c_char_to_vec(proof);
let proof = serde_json::from_slice::<BatchProof>(proof.as_slice()).unwrap();
let fork_name_str = c_char_to_str(fork_name);
let fork_id = match fork_name_str {
"bernoulli" => 2,
"curie" => 3,
"darwin" => 4,
_ => {
log::warn!("unexpected fork_name {fork_name_str}, treated as curie");
3
log::warn!("unexpected fork_name {fork_name_str}, treated as darwin");
4
}
};
let verified = panic_catch(|| {
if fork_id == 2 {
// before upgrade#3(DA Compression)
if fork_id == 3 {
// As of upgrade #3 (Curie), we verify batch proofs on-chain (EVM).
let proof = serde_json::from_slice::<BatchProofV3>(proof.as_slice()).unwrap();
verify_evm_calldata(
include_bytes!("plonk_verifier_0.10.3.bin").to_vec(),
include_bytes!("plonk_verifier_0.11.4.bin").to_vec(),
proof.calldata(),
)
} else {
VERIFIER.get().unwrap().verify_agg_evm_proof(proof)
// Post upgrade #4 (Darwin), batch proofs are not EVM-verifiable. Instead they are
// halo2 proofs meant to be bundled recursively.
let proof = serde_json::from_slice::<BatchProofV4>(proof.as_slice()).unwrap();
VERIFIER_V4.get().unwrap().verify_batch_proof(&proof)
}
});
verified.unwrap_or(false) as c_char
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn gen_bundle_proof(batch_proofs: *const c_char) -> *const c_char {
let proof_result: Result<Vec<u8>, String> = panic_catch(|| {
let batch_proofs = c_char_to_vec(batch_proofs);
let batch_proofs = serde_json::from_slice::<Vec<BatchProofV4>>(&batch_proofs)
.map_err(|e| format!("failed to deserialize batch proofs: {e:?}"))?;
let bundle = BundleProvingTask { batch_proofs };
let proof = PROVER
.get_mut()
.expect("failed to get mutable reference to PROVER.")
.gen_bundle_proof(bundle, None, OUTPUT_DIR.as_deref())
.map_err(|e| format!("failed to generate bundle proof: {e:?}"))?;
serde_json::to_vec(&proof)
.map_err(|e| format!("failed to serialize the bundle proof: {e:?}"))
})
.unwrap_or_else(|e| Err(format!("unwind error: {e:?}")));
let r = match proof_result {
Ok(proof_bytes) => ProofResult {
message: Some(proof_bytes),
error: None,
},
Err(err) => ProofResult {
message: None,
error: Some(err),
},
};
serde_json::to_vec(&r).map_or(null(), vec_to_c_char)
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn verify_bundle_proof(proof: *const c_char) -> c_char {
let proof = c_char_to_vec(proof);
let proof = serde_json::from_slice::<BundleProof>(proof.as_slice()).unwrap();
let verified = panic_catch(|| VERIFIER_V4.get().unwrap().verify_bundle_proof(proof));
verified.unwrap_or(false) as c_char
}
// This function is only used for debugging on Go side.
/// # Safety
#[no_mangle]

View File

@@ -6,16 +6,18 @@ use crate::{
},
};
use libc::c_char;
use prover::{
use prover_v3::{zkevm::Verifier as VerifierV3, ChunkProof as ChunkProofV3};
use prover_v4::{
consts::CHUNK_VK_FILENAME,
utils::init_env_and_log,
zkevm::{Prover, Verifier},
BlockTrace, ChunkProof, ChunkProvingTask,
zkevm::{Prover, Verifier as VerifierV4},
BlockTrace, ChunkProof as ChunkProofV4, ChunkProvingTask,
};
use std::{cell::OnceCell, env, ptr::null};
static mut PROVER: OnceCell<Prover> = OnceCell::new();
static mut VERIFIER: OnceCell<Verifier> = OnceCell::new();
static mut VERIFIER_V3: OnceCell<VerifierV3> = OnceCell::new();
static mut VERIFIER_V4: OnceCell<VerifierV4> = OnceCell::new();
/// # Safety
#[no_mangle]
@@ -48,9 +50,11 @@ pub unsafe extern "C" fn init_chunk_verifier(params_dir: *const c_char, assets_d
// TODO: add a settings in scroll-prover.
env::set_var("SCROLL_PROVER_ASSETS_DIR", assets_dir);
let verifier = Verifier::from_dirs(params_dir, assets_dir);
let verifier_v3 = VerifierV3::from_dirs(params_dir, assets_dir);
let verifier_v4 = VerifierV4::from_dirs(params_dir, assets_dir);
VERIFIER.set(verifier).unwrap();
VERIFIER_V3.set(verifier_v3).unwrap();
VERIFIER_V4.set(verifier_v4).unwrap();
}
/// # Safety
@@ -99,10 +103,29 @@ pub unsafe extern "C" fn gen_chunk_proof(block_traces: *const c_char) -> *const
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn verify_chunk_proof(proof: *const c_char) -> c_char {
pub unsafe extern "C" fn verify_chunk_proof(
proof: *const c_char,
fork_name: *const c_char,
) -> c_char {
let proof = c_char_to_vec(proof);
let proof = serde_json::from_slice::<ChunkProof>(proof.as_slice()).unwrap();
let verified = panic_catch(|| VERIFIER.get().unwrap().verify_chunk_proof(proof));
let fork_name_str = c_char_to_str(fork_name);
let fork_id = match fork_name_str {
"curie" => 3,
"darwin" => 4,
_ => {
log::warn!("unexpected fork_name {fork_name_str}, treated as darwin");
4
}
};
let verified = panic_catch(|| {
if fork_id == 3 {
let proof = serde_json::from_slice::<ChunkProofV3>(proof.as_slice()).unwrap();
VERIFIER_V3.get().unwrap().verify_chunk_proof(proof)
} else {
let proof = serde_json::from_slice::<ChunkProofV4>(proof.as_slice()).unwrap();
VERIFIER_V4.get().unwrap().verify_chunk_proof(proof)
}
});
verified.unwrap_or(false) as c_char
}

Binary file not shown.

View File

@@ -1,15 +1,26 @@
// BatchProver is used to:
// - Batch a list of chunk proofs
// - Bundle a list of batch proofs
void init_batch_prover(char* params_dir, char* assets_dir);
// BatchVerifier is used to:
// - Verify a batch proof
// - Verify a bundle proof
void init_batch_verifier(char* params_dir, char* assets_dir);
char* get_batch_vk();
char* check_chunk_proofs(char* chunk_proofs);
char* gen_batch_proof(char* chunk_hashes, char* chunk_proofs);
char* gen_batch_proof(char* chunk_hashes, char* chunk_proofs, char* batch_header);
char verify_batch_proof(char* proof, char* fork_name);
char* get_bundle_vk();
char* gen_bundle_proof(char* batch_proofs);
char verify_bundle_proof(char* proof);
void init_chunk_prover(char* params_dir, char* assets_dir);
void init_chunk_verifier(char* params_dir, char* assets_dir);
char* get_chunk_vk();
char* gen_chunk_proof(char* block_traces);
char verify_chunk_proof(char* proof);
char verify_chunk_proof(char* proof, char* fork_name);
char* block_traces_to_chunk_info(char* block_traces);
void free_c_chars(char* ptr);

View File

@@ -188,6 +188,31 @@ func (s ChunkProofsStatus) String() string {
}
}
// BatchProofsStatus describes the proving status of batches that belong to a bundle.
type BatchProofsStatus int
const (
// BatchProofsStatusUndefined represents an undefined batch proofs status
BatchProofsStatusUndefined BatchProofsStatus = iota
// BatchProofsStatusPending means that some batches that belong to this bundle have not been proven
BatchProofsStatusPending
// BatchProofsStatusReady means that all batches that belong to this bundle have been proven
BatchProofsStatusReady
)
func (s BatchProofsStatus) String() string {
switch s {
case BatchProofsStatusPending:
return "BatchProofsStatusPending"
case BatchProofsStatusReady:
return "BatchProofsStatusReady"
default:
return fmt.Sprintf("Undefined BatchProofsStatus (%d)", int32(s))
}
}
// RollupStatus block_batch rollup_status (pending, committing, committed, commit_failed, finalizing, finalized, finalize_skipped, finalize_failed)
type RollupStatus int

View File

@@ -1,91 +0,0 @@
package message
import (
"crypto/ecdsa"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/rlp"
)
// AuthMsg is the first message exchanged from the Prover to the Sequencer.
// It effectively acts as a registration, and makes the Prover identification
// known to the Sequencer.
type AuthMsg struct {
// Message fields
Identity *Identity `json:"message"`
// Prover signature
Signature string `json:"signature"`
}
// Identity contains all the fields to be signed by the prover.
type Identity struct {
// ProverName the prover name
ProverName string `json:"prover_name"`
// ProverVersion the prover version
ProverVersion string `json:"prover_version"`
// Challenge unique challenge generated by manager
Challenge string `json:"challenge"`
// HardForkName the hard fork name
HardForkName string `json:"hard_fork_name"`
}
// SignWithKey auth message with private key and set public key in auth message's Identity
func (a *AuthMsg) SignWithKey(priv *ecdsa.PrivateKey) error {
// Hash identity content
hash, err := a.Identity.Hash()
if err != nil {
return err
}
// Sign register message
sig, err := crypto.Sign(hash, priv)
if err != nil {
return err
}
a.Signature = hexutil.Encode(sig)
return nil
}
// Verify verifies the message of auth.
func (a *AuthMsg) Verify() (bool, error) {
hash, err := a.Identity.Hash()
if err != nil {
return false, err
}
sig := common.FromHex(a.Signature)
pk, err := crypto.SigToPub(hash, sig)
if err != nil {
return false, err
}
return crypto.VerifySignature(crypto.CompressPubkey(pk), hash, sig[:len(sig)-1]), nil
}
// PublicKey return public key from signature
func (a *AuthMsg) PublicKey() (string, error) {
hash, err := a.Identity.Hash()
if err != nil {
return "", err
}
sig := common.FromHex(a.Signature)
// recover public key
pk, err := crypto.SigToPub(hash, sig)
if err != nil {
return "", err
}
return common.Bytes2Hex(crypto.CompressPubkey(pk)), nil
}
// Hash returns the hash of the auth message, which should be the message used
// to construct the Signature.
func (i *Identity) Hash() ([]byte, error) {
byt, err := rlp.EncodeToBytes(i)
if err != nil {
return nil, err
}
hash := crypto.Keccak256Hash(byt)
return hash[:], nil
}

View File

@@ -1,89 +0,0 @@
package message
import (
"crypto/ecdsa"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/rlp"
)
// LegacyAuthMsg is the old auth message exchanged from the Prover to the Sequencer.
// It effectively acts as a registration, and makes the Prover identification
// known to the Sequencer.
type LegacyAuthMsg struct {
// Message fields
Identity *LegacyIdentity `json:"message"`
// Prover signature
Signature string `json:"signature"`
}
// LegacyIdentity contains all the fields to be signed by the prover.
type LegacyIdentity struct {
// ProverName the prover name
ProverName string `json:"prover_name"`
// ProverVersion the prover version
ProverVersion string `json:"prover_version"`
// Challenge unique challenge generated by manager
Challenge string `json:"challenge"`
}
// SignWithKey auth message with private key and set public key in auth message's Identity
func (a *LegacyAuthMsg) SignWithKey(priv *ecdsa.PrivateKey) error {
// Hash identity content
hash, err := a.Identity.Hash()
if err != nil {
return err
}
// Sign register message
sig, err := crypto.Sign(hash, priv)
if err != nil {
return err
}
a.Signature = hexutil.Encode(sig)
return nil
}
// Verify verifies the message of auth.
func (a *LegacyAuthMsg) Verify() (bool, error) {
hash, err := a.Identity.Hash()
if err != nil {
return false, err
}
sig := common.FromHex(a.Signature)
pk, err := crypto.SigToPub(hash, sig)
if err != nil {
return false, err
}
return crypto.VerifySignature(crypto.CompressPubkey(pk), hash, sig[:len(sig)-1]), nil
}
// PublicKey return public key from signature
func (a *LegacyAuthMsg) PublicKey() (string, error) {
hash, err := a.Identity.Hash()
if err != nil {
return "", err
}
sig := common.FromHex(a.Signature)
// recover public key
pk, err := crypto.SigToPub(hash, sig)
if err != nil {
return "", err
}
return common.Bytes2Hex(crypto.CompressPubkey(pk)), nil
}
// Hash returns the hash of the auth message, which should be the message used
// to construct the Signature.
func (i *LegacyIdentity) Hash() ([]byte, error) {
byt, err := rlp.EncodeToBytes(i)
if err != nil {
return nil, err
}
hash := crypto.Keccak256Hash(byt)
return hash[:], nil
}

View File

@@ -1,28 +1,11 @@
package message
import (
"crypto/ecdsa"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"github.com/scroll-tech/da-codec/encoding/codecv3"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/rlp"
)
// ProofFailureType the proof failure type
type ProofFailureType int
const (
// ProofFailureUndefined the undefined type proof failure type
ProofFailureUndefined ProofFailureType = iota
// ProofFailurePanic proof failure for prover panic
ProofFailurePanic
// ProofFailureNoPanic proof failure for no prover panic
ProofFailureNoPanic
)
// RespStatus represents status code from prover to scroll
@@ -35,7 +18,7 @@ const (
StatusProofError
)
// ProofType represents the type of prover.
// ProofType represents the type of task.
type ProofType uint8
func (r ProofType) String() string {
@@ -44,6 +27,8 @@ func (r ProofType) String() string {
return "proof type chunk"
case ProofTypeBatch:
return "proof type batch"
case ProofTypeBundle:
return "proof type bundle"
default:
return fmt.Sprintf("illegal proof type: %d", r)
}
@@ -52,93 +37,14 @@ func (r ProofType) String() string {
const (
// ProofTypeUndefined is an unknown proof type
ProofTypeUndefined ProofType = iota
// ProofTypeChunk is default prover, it only generates zk proof from traces.
// ProofTypeChunk generates a proof for a ZkEvm chunk, where the inputs are the execution traces for blocks contained in the chunk. ProofTypeChunk is the default proof type.
ProofTypeChunk
// ProofTypeBatch generates zk proof from other zk proofs and aggregate them into one proof.
// ProofTypeBatch generates zk proof from chunk proofs
ProofTypeBatch
// ProofTypeBundle generates zk proof from batch proofs
ProofTypeBundle
)
// GenerateToken generates token
func GenerateToken() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", err
}
return hex.EncodeToString(b), nil
}
// ProofMsg is the data structure sent to the coordinator.
type ProofMsg struct {
*ProofDetail `json:"zkProof"`
// Prover signature
Signature string `json:"signature"`
// Prover public key
publicKey string
}
// Sign signs the ProofMsg.
func (a *ProofMsg) Sign(priv *ecdsa.PrivateKey) error {
hash, err := a.ProofDetail.Hash()
if err != nil {
return err
}
sig, err := crypto.Sign(hash, priv)
if err != nil {
return err
}
a.Signature = hexutil.Encode(sig)
return nil
}
// Verify verifies ProofMsg.Signature.
func (a *ProofMsg) Verify() (bool, error) {
hash, err := a.ProofDetail.Hash()
if err != nil {
return false, err
}
sig := common.FromHex(a.Signature)
// recover public key
if a.publicKey == "" {
pk, err := crypto.SigToPub(hash, sig)
if err != nil {
return false, err
}
a.publicKey = common.Bytes2Hex(crypto.CompressPubkey(pk))
}
return crypto.VerifySignature(common.FromHex(a.publicKey), hash, sig[:len(sig)-1]), nil
}
// PublicKey return public key from signature
func (a *ProofMsg) PublicKey() (string, error) {
if a.publicKey == "" {
hash, err := a.ProofDetail.Hash()
if err != nil {
return "", err
}
sig := common.FromHex(a.Signature)
// recover public key
pk, err := crypto.SigToPub(hash, sig)
if err != nil {
return "", err
}
a.publicKey = common.Bytes2Hex(crypto.CompressPubkey(pk))
return a.publicKey, nil
}
return a.publicKey, nil
}
// TaskMsg is a wrapper type around db ProveTask type.
type TaskMsg struct {
UUID string `json:"uuid"`
ID string `json:"id"`
Type ProofType `json:"type,omitempty"`
BatchTaskDetail *BatchTaskDetail `json:"batch_task_detail,omitempty"`
ChunkTaskDetail *ChunkTaskDetail `json:"chunk_task_detail,omitempty"`
}
// ChunkTaskDetail is a type containing ChunkTask detail.
type ChunkTaskDetail struct {
BlockHashes []common.Hash `json:"block_hashes"`
@@ -146,30 +52,14 @@ type ChunkTaskDetail struct {
// BatchTaskDetail is a type containing BatchTask detail.
type BatchTaskDetail struct {
ChunkInfos []*ChunkInfo `json:"chunk_infos"`
ChunkProofs []*ChunkProof `json:"chunk_proofs"`
ChunkInfos []*ChunkInfo `json:"chunk_infos"`
ChunkProofs []*ChunkProof `json:"chunk_proofs"`
BatchHeader *codecv3.DABatch `json:"batch_header"`
}
// ProofDetail is the message received from provers that contains zk proof, the status of
// the proof generation succeeded, and an error message if proof generation failed.
type ProofDetail struct {
ID string `json:"id"`
Type ProofType `json:"type,omitempty"`
Status RespStatus `json:"status"`
ChunkProof *ChunkProof `json:"chunk_proof,omitempty"`
BatchProof *BatchProof `json:"batch_proof,omitempty"`
Error string `json:"error,omitempty"`
}
// Hash return proofMsg content hash.
func (z *ProofDetail) Hash() ([]byte, error) {
byt, err := rlp.EncodeToBytes(z)
if err != nil {
return nil, err
}
hash := crypto.Keccak256Hash(byt)
return hash[:], nil
// BundleTaskDetail consists of all the information required to describe the task to generate a proof for a bundle of batches.
type BundleTaskDetail struct {
BatchProofs []*BatchProof `json:"batch_proofs"`
}
// ChunkInfo is for calculating pi_hash for chunk
@@ -204,15 +94,16 @@ type ChunkProof struct {
// BatchProof includes the proof info that are required for batch verification and rollup.
type BatchProof struct {
Protocol []byte `json:"protocol"`
Proof []byte `json:"proof"`
Instances []byte `json:"instances"`
Vk []byte `json:"vk"`
// cross-reference between cooridinator computation and prover compution
GitVersion string `json:"git_version,omitempty"`
BatchHash common.Hash `json:"batch_hash"`
GitVersion string `json:"git_version,omitempty"`
}
// SanityCheck checks whether an BatchProof is in a legal format
// TODO: change to check Proof&Instance when upgrading to snark verifier v0.4
// SanityCheck checks whether a BatchProof is in a legal format
func (ap *BatchProof) SanityCheck() error {
if ap == nil {
return errors.New("agg_proof is nil")
@@ -221,8 +112,51 @@ func (ap *BatchProof) SanityCheck() error {
if len(ap.Proof) == 0 {
return errors.New("proof not ready")
}
if len(ap.Proof)%32 != 0 {
return fmt.Errorf("proof buffer has wrong length, expected: 32, got: %d", len(ap.Proof))
return fmt.Errorf("proof buffer length must be a multiple of 32, got: %d", len(ap.Proof))
}
if len(ap.Instances) == 0 {
return errors.New("instance not ready")
}
if len(ap.Vk) == 0 {
return errors.New("vk not ready")
}
return nil
}
// BundleProof includes the proof info that are required for verification of a bundle of batch proofs.
type BundleProof struct {
Proof []byte `json:"proof"`
Instances []byte `json:"instances"`
Vk []byte `json:"vk"`
// cross-reference between cooridinator computation and prover compution
GitVersion string `json:"git_version,omitempty"`
}
// SanityCheck checks whether a BundleProof is in a legal format
func (ap *BundleProof) SanityCheck() error {
if ap == nil {
return errors.New("agg_proof is nil")
}
if len(ap.Proof) == 0 {
return errors.New("proof not ready")
}
if len(ap.Proof)%32 != 0 {
return fmt.Errorf("proof buffer length must be a multiple of 32, got: %d", len(ap.Proof))
}
if len(ap.Instances) == 0 {
return errors.New("instance not ready")
}
if len(ap.Vk) == 0 {
return errors.New("vk not ready")
}
return nil

View File

@@ -1,158 +0,0 @@
package message
import (
"encoding/hex"
"testing"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
)
func TestAuthMessageSignAndVerify(t *testing.T) {
privkey, err := crypto.GenerateKey()
assert.NoError(t, err)
authMsg := &AuthMsg{
Identity: &Identity{
Challenge: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTEwMzgxNzUsIm9yaWdfaWF0IjoxNjkxMDM0NTc1fQ.HybBMsEJFhyZqtIa2iVcHUP7CEFttf708jmTMAImAWA",
ProverName: "test",
ProverVersion: "v1.0.0",
},
}
assert.NoError(t, authMsg.SignWithKey(privkey))
// Check public key.
pk, err := authMsg.PublicKey()
assert.NoError(t, err)
assert.Equal(t, common.Bytes2Hex(crypto.CompressPubkey(&privkey.PublicKey)), pk)
ok, err := authMsg.Verify()
assert.NoError(t, err)
assert.Equal(t, true, ok)
// Check public key is ok.
pub, err := authMsg.PublicKey()
assert.NoError(t, err)
pubkey := crypto.CompressPubkey(&privkey.PublicKey)
assert.Equal(t, pub, common.Bytes2Hex(pubkey))
}
func TestGenerateToken(t *testing.T) {
token, err := GenerateToken()
assert.NoError(t, err)
assert.Equal(t, 32, len(token))
}
func TestIdentityHash(t *testing.T) {
identity := &Identity{
Challenge: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTEwMzM0MTksIm9yaWdfaWF0IjoxNjkxMDI5ODE5fQ.EhkLZsj__rNPVC3ZDYBtvdh0nB8mmM_Hl82hObaIWOs",
ProverName: "test",
ProverVersion: "v1.0.0",
}
hash, err := identity.Hash()
assert.NoError(t, err)
expectedHash := "9b8b00f5655411ec1d68ba1666261281c5414aedbda932e5b6a9f7f1b114fdf2"
assert.Equal(t, expectedHash, hex.EncodeToString(hash))
}
func TestProofMessageSignVerifyPublicKey(t *testing.T) {
privkey, err := crypto.GenerateKey()
assert.NoError(t, err)
proofMsg := &ProofMsg{
ProofDetail: &ProofDetail{
ID: "testID",
Type: ProofTypeChunk,
Status: StatusOk,
ChunkProof: &ChunkProof{
StorageTrace: []byte("testStorageTrace"),
Protocol: []byte("testProtocol"),
Proof: []byte("testProof"),
Instances: []byte("testInstance"),
Vk: []byte("testVk"),
ChunkInfo: nil,
},
Error: "testError",
},
}
assert.NoError(t, proofMsg.Sign(privkey))
// Test when publicKey is not set.
ok, err := proofMsg.Verify()
assert.NoError(t, err)
assert.Equal(t, true, ok)
// Test when publicKey is already set.
ok, err = proofMsg.Verify()
assert.NoError(t, err)
assert.Equal(t, true, ok)
}
func TestProofDetailHash(t *testing.T) {
proofDetail := &ProofDetail{
ID: "testID",
Type: ProofTypeChunk,
Status: StatusOk,
ChunkProof: &ChunkProof{
StorageTrace: []byte("testStorageTrace"),
Protocol: []byte("testProtocol"),
Proof: []byte("testProof"),
Instances: []byte("testInstance"),
Vk: []byte("testVk"),
ChunkInfo: nil,
},
Error: "testError",
}
hash, err := proofDetail.Hash()
assert.NoError(t, err)
expectedHash := "01128ea9006601146ba80dbda959c96ebaefca463e78570e473a57d821db5ec1"
assert.Equal(t, expectedHash, hex.EncodeToString(hash))
}
func TestProveTypeString(t *testing.T) {
proofTypeChunk := ProofType(1)
assert.Equal(t, "proof type chunk", proofTypeChunk.String())
proofTypeBatch := ProofType(2)
assert.Equal(t, "proof type batch", proofTypeBatch.String())
illegalProof := ProofType(3)
assert.Equal(t, "illegal proof type: 3", illegalProof.String())
}
func TestProofMsgPublicKey(t *testing.T) {
privkey, err := crypto.GenerateKey()
assert.NoError(t, err)
proofMsg := &ProofMsg{
ProofDetail: &ProofDetail{
ID: "testID",
Type: ProofTypeChunk,
Status: StatusOk,
ChunkProof: &ChunkProof{
StorageTrace: []byte("testStorageTrace"),
Protocol: []byte("testProtocol"),
Proof: []byte("testProof"),
Instances: []byte("testInstance"),
Vk: []byte("testVk"),
ChunkInfo: nil,
},
Error: "testError",
},
}
assert.NoError(t, proofMsg.Sign(privkey))
// Test when publicKey is not set.
pk, err := proofMsg.PublicKey()
assert.NoError(t, err)
assert.Equal(t, common.Bytes2Hex(crypto.CompressPubkey(&privkey.PublicKey)), pk)
// Test when publicKey is already set.
proofMsg.publicKey = common.Bytes2Hex(crypto.CompressPubkey(&privkey.PublicKey))
pk, err = proofMsg.PublicKey()
assert.NoError(t, err)
assert.Equal(t, common.Bytes2Hex(crypto.CompressPubkey(&privkey.PublicKey)), pk)
}

View File

@@ -12,12 +12,8 @@ import (
type MockAppName string
var (
// EventWatcherApp the name of mock event-watcher app.
EventWatcherApp MockAppName = "event-watcher-test"
// GasOracleApp the name of mock gas-oracle app.
GasOracleApp MockAppName = "gas-oracle-test"
// MessageRelayerApp the name of mock message-relayer app.
MessageRelayerApp MockAppName = "message-relayer-test"
// RollupRelayerApp the name of mock rollup-relayer app.
RollupRelayerApp MockAppName = "rollup-relayer-test"
@@ -28,11 +24,6 @@ var (
CoordinatorAPIApp MockAppName = "coordinator-api-test"
// CoordinatorCronApp the name of mock coordinator cron app.
CoordinatorCronApp MockAppName = "coordinator-cron-test"
// ChunkProverApp the name of mock chunk prover app.
ChunkProverApp MockAppName = "chunkProver-test"
// BatchProverApp the name of mock batch prover app.
BatchProverApp MockAppName = "batchProver-test"
)
// RegisterSimulation register initializer function for integration-test.

View File

@@ -5,7 +5,7 @@ import (
"runtime/debug"
)
var tag = "v4.4.17"
var tag = "v4.4.33"
var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {

View File

@@ -1,12 +0,0 @@
### NOTE: DO NOT USE THIS FILE IF USING TESTNET'S .ENV
ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1
RINKEBY_RPC=https://eth-rinkeby.alchemyapi.io/v2/<YOUR ALCHEMY KEY>
SCROLL_L1_RPC=https://prealpha.scroll.io/l1
SCROLL_L2_RPC=https://prealpha.scroll.io/l2
RINKEBY_PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
L1_DEPLOYER_PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
L2_DEPLOYER_PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
CHAIN_ID_L2="5343541"

View File

@@ -1,4 +0,0 @@
node_modules
artifacts
cache
coverage

View File

@@ -1,24 +0,0 @@
module.exports = {
env: {
browser: false,
es2021: true,
mocha: true,
node: true,
},
plugins: ["@typescript-eslint"],
extends: [
"standard",
"plugin:prettier/recommended",
"plugin:node/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 12,
},
rules: {
"node/no-unsupported-features/es-syntax": [
"error",
{ ignores: ["modules"] },
],
},
};

17
contracts/.gitignore vendored
View File

@@ -1,17 +0,0 @@
node_modules
.env
coverage
coverage.json
typechain
# Hardhat/Foundry files
cache
cache-hardhat
artifacts
broadcast
# logs
*.log
# eslint
.eslintcache

View File

@@ -1,5 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
cd contracts
yarn lint-staged

View File

@@ -1,3 +0,0 @@
hardhat.config.ts
scripts
test

View File

@@ -1 +0,0 @@
v18.15.0

View File

@@ -1,8 +0,0 @@
node_modules
artifacts
cache
coverage*
gasReporterOutput.json
src/libraries/verifier/ZkTrieVerifier.sol
src/libraries/verifier/PatriciaMerkleTrieVerifier.sol
src/L2/predeploys/L1BlockContainer.sol

View File

@@ -1,28 +0,0 @@
{
"printWidth": 120,
"singleQuote": false,
"tabWidth": 2,
"bracketSpacing": true,
"overrides": [
{
"files": "src/**/*.sol",
"options": {
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false
}
},
{
"files": "scripts/**/*.sol",
"options": {
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false
}
}
]
}

View File

@@ -1,10 +0,0 @@
module.exports = {
skipFiles: [
'mocks',
'test',
'L2/predeploys/L1BlockContainer.sol',
'libraries/verifier/ZkTrieVerifier.sol',
'libraries/verifier/PatriciaMerkleTrieVerifier.sol'
],
istanbulReporter: ["lcov", "json"]
};

View File

@@ -1,7 +0,0 @@
{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", "^0.8.0"],
"func-visibility": ["warn", { "ignoreConstructors": true }]
}
}

View File

@@ -1 +0,0 @@
node_modules

View File

@@ -1,78 +0,0 @@
# Scroll Contracts
This directory contains the solidity code for Scroll L1 bridge and rollup contracts and L2 bridge and pre-deployed contracts. You can also find contract APIs and more details in the [`docs`](./docs) folder.
## Directory Structure
<pre>
├── <a href="./docs/">docs</a>: Documentation for the contracts
├── <a href="./integration-test/">integration-test</a>: Hardhat integration tests
├── <a href="./lib/">lib</a>: External libraries and testing tools
├── <a href="./scripts">scripts</a>: Deployment scripts
├── <a href="./src">src</a>
│ ├── <a href="./src/gas-swap/">gas-swap</a>: Utility contract that allows gas payment in other tokens
│ ├── <a href="./src/interfaces/">interfaces</a>: Common contract interfaces
│ ├── <a href="./src/L1/">L1</a>: Contracts deployed on the L1 (Ethereum)
│ │ ├── <a href="./src/L1/gateways/">gateways</a>: Gateway router and token gateway contracts
│ │ ├── <a href="./src/L1/rollup/">rollup</a>: Rollup contracts for data availability and finalization
│ │ ├── <a href="./src/L1/IL1ScrollMessenger.sol">IL1ScrollMessenger.sol</a>: L1 Scroll messenger interface
│ │ └── <a href="./src/L1/L1ScrollMessenger.sol">L1ScrollMessenger.sol</a>: L1 Scroll messenger contract
│ ├── <a href="./src/L2/">L2</a>: Contracts deployed on the L2 (Scroll)
│ │ ├── <a href="./src/L2/gateways/">gateways</a>: Gateway router and token gateway contracts
│ │ ├── <a href="./src/L2/predeploys/">predeploys</a>: Pre-deployed contracts on L2
│ │ ├── <a href="./src/L2/IL2ScrollMessenger.sol">IL2ScrollMessenger.sol</a>: L2 Scroll messenger interface
│ │ └── <a href="./src/L2/L2ScrollMessenger.sol">L2ScrollMessenger.sol</a>: L2 Scroll messenger contract
│ ├── <a href="./src/libraries/">libraries</a>: Shared contract libraries
│ ├── <a href="./src/misc/">misc</a>: Miscellaneous contracts
│ ├── <a href="./src/mocks/">mocks</a>: Mock contracts used in the testing
│ ├── <a href="./src/rate-limiter/">rate-limiter</a>: Rater limiter contract
│ └── <a href="./src/test/">test</a>: Unit tests in solidity
├── <a href="./foundry.toml">foundry.toml</a>: Foundry configuration
├── <a href="./hardhat.config.ts">hardhat.config.ts</a>: Hardhat configuration
├── <a href="./remappings.txt">remappings.txt</a>: Foundry dependency mappings
...
</pre>
## Dependencies
### Node.js
First install [`Node.js`](https://nodejs.org/en) and [`npm`](https://www.npmjs.com/).
Run the following command to install [`yarn`](https://classic.yarnpkg.com/en/):
```bash
npm install --global yarn
```
### Foundry
Install `foundryup`, the Foundry toolchain installer:
```bash
curl -L https://foundry.paradigm.xyz | bash
```
If you do not want to use the redirect, feel free to manually download the `foundryup` installation script from [here](https://raw.githubusercontent.com/foundry-rs/foundry/master/foundryup/foundryup).
Then, run `foundryup` in a new terminal session or after reloading `PATH`.
Other ways to install Foundry can be found [here](https://github.com/foundry-rs/foundry#installation).
### Hardhat
Run the following command to install [Hardhat](https://hardhat.org/) and other dependencies.
```
yarn install
```
## Build
- Run `git submodule update --init --recursive` to initialize git submodules.
- Run `yarn prettier:solidity` to run linting in fix mode, will auto-format all solidity codes.
- Run `yarn prettier` to run linting in fix mode, will auto-format all typescript codes.
- Run `yarn prepare` to install the precommit linting hook.
- Run `forge build` to compile contracts with foundry.
- Run `npx hardhat compile` to compile with hardhat.
- Run `forge test -vvv` to run foundry units tests. It will compile all contracts before running the unit tests.
- Run `npx hardhat test` to run integration tests. It may not compile all contracts before running, it's better to run `npx hardhat compile` first.

View File

@@ -1,3 +0,0 @@
declare module "circomlib/src/evmasm";
declare module "circomlib/src/poseidon_gencontract";
declare module "circomlib/src/poseidon_constants";

View File

@@ -1,16 +0,0 @@
# Deployments
## local testnet
```bash
# start local hardhat node
npx hardhat node
```
### layer 1
Contract addresses can be found in [deployments](./l1geth.json).
### layer 2
Contract addresses can be found in [deployments](./l2geth.json).

View File

@@ -1,23 +0,0 @@
{
"ProxyAdmin": null,
"ZKRollup": {
"implementation": null,
"proxy": null
},
"L1ScrollMessenger": {
"implementation": null,
"proxy": null
},
"L1GatewayRouter": {
"implementation": null,
"proxy": null
},
"L1StandardERC20Gateway": {
"implementation": null,
"proxy": null
},
"L1WETHGateway": {
"implementation": null,
"proxy": null
}
}

View File

@@ -1,20 +0,0 @@
{
"ProxyAdmin": null,
"WETH": null,
"Whitelist": null,
"ScrollStandardERC20": null,
"ScrollStandardERC20Factory": null,
"L2ScrollMessenger": null,
"L2GatewayRouter": {
"implementation": null,
"proxy": null
},
"L2StandardERC20Gateway": {
"implementation": null,
"proxy": null
},
"L2WETHGateway": {
"implementation": null,
"proxy": null
}
}

View File

@@ -1,599 +0,0 @@
# L1ERC1155Gateway
> L1ERC1155Gateway
The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT on layer 1 and finalize withdraw the NFTs from layer 2.
*The deposited NFTs are held in this gateway. On finalizing withdraw, the corresponding NFT will be transfer to the recipient directly. This will be changed if we have more specific scenarios.*
## Methods
### batchDepositERC1155
```solidity
function batchDepositERC1155(address _token, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external payable
```
Deposit a list of some ERC1155 NFT to caller&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT on layer 1. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _amounts | uint256[] | The list of corresponding number of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### batchDepositERC1155
```solidity
function batchDepositERC1155(address _token, address _to, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external payable
```
Deposit a list of some ERC1155 NFT to a recipient&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _amounts | uint256[] | The list of corresponding number of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### depositERC1155
```solidity
function depositERC1155(address _token, address _to, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some ERC1155 NFT to a recipient&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenId | uint256 | The token id to deposit. |
| _amount | uint256 | The amount of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### depositERC1155
```solidity
function depositERC1155(address _token, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some ERC1155 NFT to caller&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT on layer 1. |
| _tokenId | uint256 | The token id to deposit. |
| _amount | uint256 | The amount of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### finalizeBatchWithdrawERC1155
```solidity
function finalizeBatchWithdrawERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds, uint256[] _amounts) external nonpayable
```
Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipient&#39;s account on layer 1. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC1155Gateway on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
| _amounts | uint256[] | The list of corresponding number of token to withdraw. |
### finalizeWithdrawERC1155
```solidity
function finalizeWithdrawERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId, uint256 _amount) external nonpayable
```
Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient&#39;s account on layer 1. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC1155Gateway on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenId | uint256 | The token id to withdraw. |
| _amount | uint256 | The amount of token to withdraw. |
### initialize
```solidity
function initialize(address _counterpart, address _messenger) external nonpayable
```
Initialize the storage of L1ERC1155Gateway.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of L2ERC1155Gateway in L2. |
| _messenger | address | The address of L1ScrollMessenger in L1. |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### onDropMessage
```solidity
function onDropMessage(bytes _message) external payable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _message | bytes | undefined |
### onERC1155BatchReceived
```solidity
function onERC1155BatchReceived(address, address, uint256[], uint256[], bytes) external nonpayable returns (bytes4)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256[] | undefined |
| _3 | uint256[] | undefined |
| _4 | bytes | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes4 | undefined |
### onERC1155Received
```solidity
function onERC1155Received(address, address, uint256, uint256, bytes) external nonpayable returns (bytes4)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | uint256 | undefined |
| _4 | bytes | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes4 | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### supportsInterface
```solidity
function supportsInterface(bytes4 interfaceId) external view returns (bool)
```
*See {IERC165-supportsInterface}.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| interfaceId | bytes4 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### tokenMapping
```solidity
function tokenMapping(address) external view returns (address)
```
Mapping from l1 token address to l2 token address for ERC1155 NFT.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### updateTokenMapping
```solidity
function updateTokenMapping(address _l1Token, address _l2Token) external nonpayable
```
Update layer 2 to layer 2 token mapping.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of ERC1155 token on layer 1. |
| _l2Token | address | The address of corresponding ERC1155 token on layer 2. |
## Events
### BatchDepositERC1155
```solidity
event BatchDepositERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds, uint256[] _amounts)
```
Emitted when the ERC1155 NFT is batch deposited to gateway on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenIds | uint256[] | The list of token ids of the ERC1155 NFT to deposit on layer 1. |
| _amounts | uint256[] | The list of corresponding number of token to deposit on layer 1. |
### BatchRefundERC1155
```solidity
event BatchRefundERC1155(address indexed token, address indexed recipient, uint256[] tokenIds, uint256[] amounts)
```
Emitted when some ERC1155 token is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| tokenIds | uint256[] | The list of ids of token refunded. |
| amounts | uint256[] | The list of amount of token refunded. |
### DepositERC1155
```solidity
event DepositERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId, uint256 _amount)
```
Emitted when the ERC1155 NFT is deposited to gateway on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenId | uint256 | The token id of the ERC1155 NFT to deposit on layer 1. |
| _amount | uint256 | The number of token to deposit on layer 1. |
### FinalizeBatchWithdrawERC1155
```solidity
event FinalizeBatchWithdrawERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds, uint256[] _amounts)
```
Emitted when the ERC1155 NFT is batch transferred to recipient on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 2. |
| _to | address | The address of recipient on layer 1. |
| _tokenIds | uint256[] | The list of token ids of the ERC1155 NFT to withdraw from layer 2. |
| _amounts | uint256[] | The list of corresponding number of token to withdraw from layer 2. |
### FinalizeWithdrawERC1155
```solidity
event FinalizeWithdrawERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId, uint256 _amount)
```
Emitted when the ERC1155 NFT is transferred to recipient on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 2. |
| _to | address | The address of recipient on layer 1. |
| _tokenId | uint256 | The token id of the ERC1155 NFT to withdraw from layer 2. |
| _amount | uint256 | The number of token to withdraw from layer 2. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC1155
```solidity
event RefundERC1155(address indexed token, address indexed recipient, uint256 tokenId, uint256 amount)
```
Emitted when some ERC1155 token is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| tokenId | uint256 | The id of token refunded. |
| amount | uint256 | The amount of token refunded. |
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token)
```
Emitted when token mapping for ERC1155 token is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC1155 token in layer 1. |
| oldL2Token `indexed` | address | The address of the old corresponding ERC1155 token in layer 2. |
| newL2Token `indexed` | address | The address of the new corresponding ERC1155 token in layer 2. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,538 +0,0 @@
# L1ERC721Gateway
> L1ERC721Gateway
The `L1ERC721Gateway` is used to deposit ERC721 compatible NFT on layer 1 and finalize withdraw the NFTs from layer 2.
*The deposited NFTs are held in this gateway. On finalizing withdraw, the corresponding NFT will be transfer to the recipient directly. This will be changed if we have more specific scenarios.*
## Methods
### batchDepositERC721
```solidity
function batchDepositERC721(address _token, address _to, uint256[] _tokenIds, uint256 _gasLimit) external payable
```
Deposit a list of some ERC721 NFT to a recipient&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### batchDepositERC721
```solidity
function batchDepositERC721(address _token, uint256[] _tokenIds, uint256 _gasLimit) external payable
```
Deposit a list of some ERC721 NFT to caller&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT on layer 1. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### depositERC721
```solidity
function depositERC721(address _token, address _to, uint256 _tokenId, uint256 _gasLimit) external payable
```
Deposit some ERC721 NFT to a recipient&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenId | uint256 | The token id to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### depositERC721
```solidity
function depositERC721(address _token, uint256 _tokenId, uint256 _gasLimit) external payable
```
Deposit some ERC721 NFT to caller&#39;s account on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT on layer 1. |
| _tokenId | uint256 | The token id to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
### finalizeBatchWithdrawERC721
```solidity
function finalizeBatchWithdrawERC721(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds) external nonpayable
```
Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s account on layer 1.
*Requirements: - The function should only be called by L1ScrollMessenger. - The function should also only be called by L2ERC721Gateway on layer 2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
### finalizeWithdrawERC721
```solidity
function finalizeWithdrawERC721(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId) external nonpayable
```
Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s account on layer 1.
*Requirements: - The function should only be called by L1ScrollMessenger. - The function should also only be called by L2ERC721Gateway on layer 2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenId | uint256 | The token id to withdraw. |
### initialize
```solidity
function initialize(address _counterpart, address _messenger) external nonpayable
```
Initialize the storage of L1ERC721Gateway.
*The parameters `_counterpart` and `_messenger` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of L2ERC721Gateway in L2. |
| _messenger | address | The address of L1ScrollMessenger in L1. |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### onDropMessage
```solidity
function onDropMessage(bytes _message) external payable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _message | bytes | undefined |
### onERC721Received
```solidity
function onERC721Received(address, address, uint256, bytes) external nonpayable returns (bytes4)
```
*See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | bytes | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes4 | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### tokenMapping
```solidity
function tokenMapping(address) external view returns (address)
```
Mapping from l1 token address to l2 token address for ERC721 NFT.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### updateTokenMapping
```solidity
function updateTokenMapping(address _l1Token, address _l2Token) external nonpayable
```
Update layer 2 to layer 2 token mapping.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of ERC721 token on layer 1. |
| _l2Token | address | The address of corresponding ERC721 token on layer 2. |
## Events
### BatchDepositERC721
```solidity
event BatchDepositERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds)
```
Emitted when the ERC721 NFT is batch deposited to gateway on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenIds | uint256[] | The list of token ids of the ERC721 NFT to deposit on layer 1. |
### BatchRefundERC721
```solidity
event BatchRefundERC721(address indexed token, address indexed recipient, uint256[] tokenIds)
```
Emitted when a batch of ERC721 tokens are refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| tokenIds | uint256[] | The list of token ids of the ERC721 NFT refunded. |
### DepositERC721
```solidity
event DepositERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId)
```
Emitted when the ERC721 NFT is deposited to gateway on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenId | uint256 | The token id of the ERC721 NFT to deposit on layer 1. |
### FinalizeBatchWithdrawERC721
```solidity
event FinalizeBatchWithdrawERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds)
```
Emitted when the ERC721 NFT is batch transferred to recipient on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 2. |
| _to | address | The address of recipient on layer 1. |
| _tokenIds | uint256[] | The list of token ids of the ERC721 NFT to withdraw from layer 2. |
### FinalizeWithdrawERC721
```solidity
event FinalizeWithdrawERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId)
```
Emitted when the ERC721 NFT is transferred to recipient on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| _l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| _from `indexed` | address | The address of sender on layer 2. |
| _to | address | The address of recipient on layer 1. |
| _tokenId | uint256 | The token id of the ERC721 NFT to withdraw from layer 2. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC721
```solidity
event RefundERC721(address indexed token, address indexed recipient, uint256 tokenId)
```
Emitted when some ERC721 token is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| tokenId | uint256 | The id of token refunded. |
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token)
```
Emitted when token mapping for ERC721 token is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC721 token in layer 1. |
| oldL2Token `indexed` | address | The address of the old corresponding ERC721 token in layer 2. |
| newL2Token `indexed` | address | The address of the new corresponding ERC721 token in layer 2. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,620 +0,0 @@
# L1GatewayRouter
> L1GatewayRouter
The `L1GatewayRouter` is the main entry for depositing Ether and ERC20 tokens. All deposited tokens are routed to corresponding gateways.
*One can also use this contract to query L1/L2 token address mapping. In the future, ERC-721 and ERC-1155 tokens will be added to the router too.*
## Methods
### ERC20Gateway
```solidity
function ERC20Gateway(address) external view returns (address)
```
Mapping from ERC20 token address to corresponding L1ERC20Gateway.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### defaultERC20Gateway
```solidity
function defaultERC20Gateway() external view returns (address)
```
The addess of default ERC20 gateway, normally the L1StandardERC20Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### depositERC20
```solidity
function depositERC20(address _token, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some token to a caller&#39;s account on L2.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositERC20
```solidity
function depositERC20(address _token, address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some token to a recipient&#39;s account on L2.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _to | address | The address of recipient&#39;s account on L2. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositERC20AndCall
```solidity
function depositERC20AndCall(address _token, address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Deposit some token to a recipient&#39;s account on L2 and call.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _to | address | The address of recipient&#39;s account on L2. |
| _amount | uint256 | The amount of token to transfer. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositETH
```solidity
function depositETH(uint256 _amount, uint256 _gasLimit) external payable
```
Deposit ETH to caller&#39;s account in L2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### depositETH
```solidity
function depositETH(address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit ETH to some recipient&#39;s account in L2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### depositETHAndCall
```solidity
function depositETHAndCall(address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Deposit ETH to some recipient&#39;s account in L2 and call the target contract.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
### ethGateway
```solidity
function ethGateway() external view returns (address)
```
The address of L1ETHGateway.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### finalizeWithdrawERC20
```solidity
function finalizeWithdrawERC20(address, address, address, address, uint256, bytes) external payable
```
Complete ERC20 withdraw from L2 to L1 and send fund to recipient&#39;s account in L1.
*Make this function payable to handle WETH deposit/withdraw. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC20Gateway in L2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | address | undefined |
| _3 | address | undefined |
| _4 | uint256 | undefined |
| _5 | bytes | undefined |
### finalizeWithdrawETH
```solidity
function finalizeWithdrawETH(address, address, uint256, bytes) external payable
```
Complete ETH withdraw from L2 to L1 and send fund to recipient&#39;s account in L1.
*This function should only be called by L1ScrollMessenger. This function should also only be called by L1ETHGateway in L2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | bytes | undefined |
### gatewayInContext
```solidity
function gatewayInContext() external view returns (address)
```
The address of gateway in current execution context.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### getERC20Gateway
```solidity
function getERC20Gateway(address _token) external view returns (address)
```
Return the corresponding gateway address for given token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token to query. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### getL2ERC20Address
```solidity
function getL2ERC20Address(address _l1Address) external view returns (address)
```
Return the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Address | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _ethGateway, address _defaultERC20Gateway) external nonpayable
```
Initialize the storage of L1GatewayRouter.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _ethGateway | address | The address of L1ETHGateway contract. |
| _defaultERC20Gateway | address | The address of default ERC20 Gateway contract. |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### requestERC20
```solidity
function requestERC20(address _sender, address _token, uint256 _amount) external nonpayable returns (uint256)
```
Request ERC20 token transfer from users to gateways.
*All the gateways should have reentrancy guard to prevent potential attack though this function.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _sender | address | undefined |
| _token | address | undefined |
| _amount | uint256 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### setDefaultERC20Gateway
```solidity
function setDefaultERC20Gateway(address _newDefaultERC20Gateway) external nonpayable
```
Update the address of default ERC20 gateway contract.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newDefaultERC20Gateway | address | undefined |
### setERC20Gateway
```solidity
function setERC20Gateway(address[] _tokens, address[] _gateways) external nonpayable
```
Update the mapping from token address to gateway address.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _tokens | address[] | The list of addresses of tokens to update. |
| _gateways | address[] | The list of addresses of gateways to update. |
### setETHGateway
```solidity
function setETHGateway(address _newEthGateway) external nonpayable
```
Update the address of ETH gateway contract.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newEthGateway | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
## Events
### DepositERC20
```solidity
event DepositERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when someone deposit ERC20 token from L1 to L2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L1. |
| to | address | The address of recipient in L2. |
| amount | uint256 | The amount of token will be deposited from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### DepositETH
```solidity
event DepositETH(address indexed from, address indexed to, uint256 amount, bytes data)
```
Emitted when someone deposit ETH from L1 to L2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| from `indexed` | address | The address of sender in L1. |
| to `indexed` | address | The address of recipient in L2. |
| amount | uint256 | The amount of ETH will be deposited from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### FinalizeWithdrawERC20
```solidity
event FinalizeWithdrawERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L2. |
| to | address | The address of recipient in L1. |
| amount | uint256 | The amount of token withdrawn from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
### FinalizeWithdrawETH
```solidity
event FinalizeWithdrawETH(address indexed from, address indexed to, uint256 amount, bytes data)
```
Emitted when ETH is withdrawn from L2 to L1 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| from `indexed` | address | The address of sender in L2. |
| to `indexed` | address | The address of recipient in L1. |
| amount | uint256 | The amount of ETH withdrawn from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC20
```solidity
event RefundERC20(address indexed token, address indexed recipient, uint256 amount)
```
Emitted when some ERC20 token is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| amount | uint256 | The amount of token refunded to receiver. |
### RefundETH
```solidity
event RefundETH(address indexed recipient, uint256 amount)
```
Emitted when some ETH is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| recipient `indexed` | address | The address of receiver in L1. |
| amount | uint256 | The amount of ETH refunded to receiver. |
### SetDefaultERC20Gateway
```solidity
event SetDefaultERC20Gateway(address indexed oldDefaultERC20Gateway, address indexed newDefaultERC20Gateway)
```
Emitted when the address of default ERC20 Gateway is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| oldDefaultERC20Gateway `indexed` | address | The address of the old default ERC20 Gateway. |
| newDefaultERC20Gateway `indexed` | address | The address of the new default ERC20 Gateway. |
### SetERC20Gateway
```solidity
event SetERC20Gateway(address indexed token, address indexed oldGateway, address indexed newGateway)
```
Emitted when the `gateway` for `token` is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of token updated. |
| oldGateway `indexed` | address | The corresponding address of the old gateway. |
| newGateway `indexed` | address | The corresponding address of the new gateway. |
### SetETHGateway
```solidity
event SetETHGateway(address indexed oldETHGateway, address indexed newEthGateway)
```
Emitted when the address of ETH Gateway is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| oldETHGateway `indexed` | address | The address of the old ETH Gateway. |
| newEthGateway `indexed` | address | The address of the new ETH Gateway. |

View File

@@ -1,627 +0,0 @@
# L1ScrollMessenger
> L1ScrollMessenger
The `L1ScrollMessenger` contract can: 1. send messages from layer 1 to layer 2; 2. relay messages from layer 2 layer 1; 3. replay failed message by replacing the gas limit; 4. drop expired message due to sequencer problems.
*All deposited Ether (including `WETH` deposited throng `L1WETHGateway`) will locked in this contract.*
## Methods
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of counterpart ScrollMessenger contract in L1/L2.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### dropMessage
```solidity
function dropMessage(address _from, address _to, uint256 _value, uint256 _messageNonce, bytes _message) external nonpayable
```
Drop a skipped message.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _messageNonce | uint256 | undefined |
| _message | bytes | undefined |
### feeVault
```solidity
function feeVault() external view returns (address)
```
The address of fee vault, collecting cross domain messaging fee.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _feeVault, address _rollup, address _messageQueue) external nonpayable
```
Initialize the storage of L1ScrollMessenger.
*The parameters `_counterpart`, `_rollup` and `_messageQueue` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of L2ScrollMessenger contract in L2. |
| _feeVault | address | The address of fee vault, which will be used to collect relayer fee. |
| _rollup | address | The address of ScrollChain contract. |
| _messageQueue | address | The address of L1MessageQueue contract. |
### isL1MessageDropped
```solidity
function isL1MessageDropped(bytes32) external view returns (bool)
```
Mapping from L1 message hash to drop status.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### isL2MessageExecuted
```solidity
function isL2MessageExecuted(bytes32) external view returns (bool)
```
Mapping from L2 message hash to a boolean value indicating if the message has been successfully executed.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### maxReplayTimes
```solidity
function maxReplayTimes() external view returns (uint256)
```
The maximum number of times each L1 message can be replayed.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### messageQueue
```solidity
function messageQueue() external view returns (address)
```
The address of L1MessageQueue contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### messageSendTimestamp
```solidity
function messageSendTimestamp(bytes32) external view returns (uint256)
```
Mapping from L1 message hash to the timestamp when the message is sent.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### paused
```solidity
function paused() external view returns (bool)
```
*Returns true if the contract is paused, and false otherwise.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### prevReplayIndex
```solidity
function prevReplayIndex(uint256) external view returns (uint256)
```
Mapping from queue index to previous replay queue index.
*If a message `x` was replayed 3 times with index `q1`, `q2` and `q3`, the value of `prevReplayIndex` and `replayStates` will be `replayStates[hash(x)].lastIndex = q3`, `replayStates[hash(x)].times = 3`, `prevReplayIndex[q3] = q2`, `prevReplayIndex[q2] = q1`, `prevReplayIndex[q1] = x` and `prevReplayIndex[x]=nil`.The index `x` that `prevReplayIndex[x]=nil` is used as the termination of the list. Usually we use `0` to represent `nil`, but we cannot distinguish it with the first message with index zero. So a nonzero offset `1` is added to the value of `prevReplayIndex[x]` to avoid such situation.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### relayMessageWithProof
```solidity
function relayMessageWithProof(address _from, address _to, uint256 _value, uint256 _nonce, bytes _message, IL1ScrollMessenger.L2MessageProof _proof) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
| _proof | IL1ScrollMessenger.L2MessageProof | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### replayMessage
```solidity
function replayMessage(address _from, address _to, uint256 _value, uint256 _messageNonce, bytes _message, uint32 _newGasLimit, address _refundAddress) external payable
```
Replay an existing message.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _messageNonce | uint256 | undefined |
| _message | bytes | undefined |
| _newGasLimit | uint32 | undefined |
| _refundAddress | address | undefined |
### replayStates
```solidity
function replayStates(bytes32) external view returns (uint128 times, uint128 lastIndex)
```
Mapping from L1 message hash to replay state.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| times | uint128 | undefined |
| lastIndex | uint128 | undefined |
### rollup
```solidity
function rollup() external view returns (address)
```
The address of Rollup contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### sendMessage
```solidity
function sendMessage(address _to, uint256 _value, bytes _message, uint256 _gasLimit, address _refundAddress) external payable
```
Send cross chain message from L1 to L2 or L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _value | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
| _refundAddress | address | undefined |
### sendMessage
```solidity
function sendMessage(address _to, uint256 _value, bytes _message, uint256 _gasLimit) external payable
```
Send cross chain message from L1 to L2 or L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _value | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
### setPause
```solidity
function setPause(bool _status) external nonpayable
```
Pause the contract
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _status | bool | The pause status to update. |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### updateFeeVault
```solidity
function updateFeeVault(address _newFeeVault) external nonpayable
```
Update fee vault contract.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newFeeVault | address | The address of new fee vault contract. |
### updateMaxReplayTimes
```solidity
function updateMaxReplayTimes(uint256 _newMaxReplayTimes) external nonpayable
```
Update max replay times.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newMaxReplayTimes | uint256 | The new max replay times. |
### xDomainMessageSender
```solidity
function xDomainMessageSender() external view returns (address)
```
See {IScrollMessenger-xDomainMessageSender}
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
## Events
### FailedRelayedMessage
```solidity
event FailedRelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is failed to relay.
#### Parameters
| Name | Type | Description |
|---|---|---|
| messageHash `indexed` | bytes32 | The hash of the message. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### Paused
```solidity
event Paused(address account)
```
*Emitted when the pause is triggered by `account`.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| account | address | undefined |
### RelayedMessage
```solidity
event RelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is relayed successfully.
#### Parameters
| Name | Type | Description |
|---|---|---|
| messageHash `indexed` | bytes32 | The hash of the message. |
### SentMessage
```solidity
event SentMessage(address indexed sender, address indexed target, uint256 value, uint256 messageNonce, uint256 gasLimit, bytes message)
```
Emitted when a cross domain message is sent.
#### Parameters
| Name | Type | Description |
|---|---|---|
| sender `indexed` | address | The address of the sender who initiates the message. |
| target `indexed` | address | The address of target contract to call. |
| value | uint256 | The amount of value passed to the target contract. |
| messageNonce | uint256 | The nonce of the message. |
| gasLimit | uint256 | The optional gas limit passed to L1 or L2. |
| message | bytes | The calldata passed to the target contract. |
### Unpaused
```solidity
event Unpaused(address account)
```
*Emitted when the pause is lifted by `account`.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| account | address | undefined |
### UpdateFeeVault
```solidity
event UpdateFeeVault(address _oldFeeVault, address _newFeeVault)
```
Emitted when owner updates fee vault contract.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _oldFeeVault | address | The address of old fee vault contract. |
| _newFeeVault | address | The address of new fee vault contract. |
### UpdateMaxReplayTimes
```solidity
event UpdateMaxReplayTimes(uint256 oldMaxReplayTimes, uint256 newMaxReplayTimes)
```
Emitted when the maximum number of times each message can be replayed is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| oldMaxReplayTimes | uint256 | The old maximum number of times each message can be replayed. |
| newMaxReplayTimes | uint256 | The new maximum number of times each message can be replayed. |
## Errors
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,423 +0,0 @@
# L1StandardERC20Gateway
> L1StandardERC20Gateway
The `L1StandardERC20Gateway` is used to deposit standard ERC20 tokens on layer 1 and finalize withdraw the tokens from layer 2.
*The deposited ERC20 tokens are held in this gateway. On finalizing withdraw, the corresponding token will be transfer to the recipient directly. Any ERC20 that requires non-standard functionality should use a separate gateway.*
## Methods
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### depositERC20
```solidity
function depositERC20(address _token, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some token to a caller&#39;s account on L2.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositERC20
```solidity
function depositERC20(address _token, address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some token to a recipient&#39;s account on L2.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _to | address | The address of recipient&#39;s account on L2. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositERC20AndCall
```solidity
function depositERC20AndCall(address _token, address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Deposit some token to a recipient&#39;s account on L2 and call.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _to | address | The address of recipient&#39;s account on L2. |
| _amount | uint256 | The amount of token to transfer. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### finalizeWithdrawERC20
```solidity
function finalizeWithdrawERC20(address _l1Token, address _l2Token, address _from, address _to, uint256 _amount, bytes _data) external payable
```
Complete ERC20 withdraw from L2 to L1 and send fund to recipient&#39;s account in L1.
*Make this function payable to handle WETH deposit/withdraw. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC20Gateway in L2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding L1 token. |
| _l2Token | address | The address of corresponding L2 token. |
| _from | address | The address of account who withdraw the token in L2. |
| _to | address | The address of recipient in L1 to receive the token. |
| _amount | uint256 | The amount of the token to withdraw. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
### getL2ERC20Address
```solidity
function getL2ERC20Address(address _l1Token) external view returns (address)
```
Return the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of l1 token. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _router, address _messenger, address, address) external nonpayable
```
Initialize the storage of L1StandardERC20Gateway.
*The parameters `_counterpart`, `_router`, `_messenger`, `_l2TokenImplementation` and `_l2TokenFactory` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of L2StandardERC20Gateway in L2. |
| _router | address | The address of L1GatewayRouter in L1. |
| _messenger | address | The address of L1ScrollMessenger in L1. |
| _3 | address | undefined |
| _4 | address | undefined |
### l2TokenFactory
```solidity
function l2TokenFactory() external view returns (address)
```
The address of ScrollStandardERC20Factory contract in L2.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### l2TokenImplementation
```solidity
function l2TokenImplementation() external view returns (address)
```
The address of ScrollStandardERC20 implementation in L2.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### onDropMessage
```solidity
function onDropMessage(bytes _message) external payable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _message | bytes | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
## Events
### DepositERC20
```solidity
event DepositERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when someone deposit ERC20 token from L1 to L2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L1. |
| to | address | The address of recipient in L2. |
| amount | uint256 | The amount of token will be deposited from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### FinalizeWithdrawERC20
```solidity
event FinalizeWithdrawERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L2. |
| to | address | The address of recipient in L1. |
| amount | uint256 | The amount of token withdrawn from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC20
```solidity
event RefundERC20(address indexed token, address indexed recipient, uint256 amount)
```
Emitted when some ERC20 token is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| amount | uint256 | The amount of token refunded to receiver. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,421 +0,0 @@
# L1WETHGateway
> L1WETHGateway
The `L1WETHGateway` contract is used to deposit `WETH` token on layer 1 and finalize withdraw `WETH` from layer 2.
*The deposited WETH tokens are not held in the gateway. It will first be unwrapped as Ether and then the Ether will be sent to the `L1ScrollMessenger` contract. On finalizing withdraw, the Ether will be transferred from `L1ScrollMessenger`, then wrapped as WETH and finally transfer to recipient.*
## Methods
### WETH
```solidity
function WETH() external view returns (address)
```
The address of L1 WETH address.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### depositERC20
```solidity
function depositERC20(address _token, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some token to a caller&#39;s account on L2.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositERC20
```solidity
function depositERC20(address _token, address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some token to a recipient&#39;s account on L2.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _to | address | The address of recipient&#39;s account on L2. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### depositERC20AndCall
```solidity
function depositERC20AndCall(address _token, address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Deposit some token to a recipient&#39;s account on L2 and call.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L1. |
| _to | address | The address of recipient&#39;s account on L2. |
| _amount | uint256 | The amount of token to transfer. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### finalizeWithdrawERC20
```solidity
function finalizeWithdrawERC20(address _l1Token, address _l2Token, address _from, address _to, uint256 _amount, bytes _data) external payable
```
Complete ERC20 withdraw from L2 to L1 and send fund to recipient&#39;s account in L1.
*Make this function payable to handle WETH deposit/withdraw. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC20Gateway in L2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding L1 token. |
| _l2Token | address | The address of corresponding L2 token. |
| _from | address | The address of account who withdraw the token in L2. |
| _to | address | The address of recipient in L1 to receive the token. |
| _amount | uint256 | The amount of the token to withdraw. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
### getL2ERC20Address
```solidity
function getL2ERC20Address(address) external view returns (address)
```
Return the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _router, address _messenger) external nonpayable
```
Initialize the storage of L1WETHGateway.
*The parameters `_counterpart`, `_router` and `_messenger` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of L2ETHGateway in L2. |
| _router | address | The address of L1GatewayRouter in L1. |
| _messenger | address | The address of L1ScrollMessenger in L1. |
### l2WETH
```solidity
function l2WETH() external view returns (address)
```
The address of L2 WETH address.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### onDropMessage
```solidity
function onDropMessage(bytes _message) external payable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _message | bytes | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
## Events
### DepositERC20
```solidity
event DepositERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when someone deposit ERC20 token from L1 to L2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L1. |
| to | address | The address of recipient in L2. |
| amount | uint256 | The amount of token will be deposited from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### FinalizeWithdrawERC20
```solidity
event FinalizeWithdrawERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L2. |
| to | address | The address of recipient in L1. |
| amount | uint256 | The amount of token withdrawn from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC20
```solidity
event RefundERC20(address indexed token, address indexed recipient, uint256 amount)
```
Emitted when some ERC20 token is refunded.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of the token in L1. |
| recipient `indexed` | address | The address of receiver in L1. |
| amount | uint256 | The amount of token refunded to receiver. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,545 +0,0 @@
# L2ERC1155Gateway
> L2ERC1155Gateway
The `L2ERC1155Gateway` is used to withdraw ERC1155 compatible NFTs on layer 2 and finalize deposit the NFTs from layer 1.
*The withdrawn NFTs tokens will be burned directly. On finalizing deposit, the corresponding NFT will be minted and transferred to the recipient. This will be changed if we have more specific scenarios.*
## Methods
### batchWithdrawERC1155
```solidity
function batchWithdrawERC1155(address _token, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external payable
```
Batch withdraw a list of ERC1155 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _tokenIds | uint256[] | undefined |
| _amounts | uint256[] | undefined |
| _gasLimit | uint256 | undefined |
### batchWithdrawERC1155
```solidity
function batchWithdrawERC1155(address _token, address _to, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external payable
```
Batch withdraw a list of ERC1155 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| _amounts | uint256[] | undefined |
| _gasLimit | uint256 | undefined |
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### finalizeBatchDepositERC1155
```solidity
function finalizeBatchDepositERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds, uint256[] _amounts) external nonpayable
```
Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway on layer 1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| _amounts | uint256[] | undefined |
### finalizeDepositERC1155
```solidity
function finalizeDepositERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId, uint256 _amount) external nonpayable
```
Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway on layer 1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _messenger) external nonpayable
```
Initialize the storage of `L2ERC1155Gateway`.
*The parameters `_counterpart` and `_messenger` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of `L1ERC1155Gateway` contract in L1. |
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### onERC1155BatchReceived
```solidity
function onERC1155BatchReceived(address, address, uint256[], uint256[], bytes) external nonpayable returns (bytes4)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256[] | undefined |
| _3 | uint256[] | undefined |
| _4 | bytes | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes4 | undefined |
### onERC1155Received
```solidity
function onERC1155Received(address, address, uint256, uint256, bytes) external nonpayable returns (bytes4)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | uint256 | undefined |
| _4 | bytes | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes4 | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### supportsInterface
```solidity
function supportsInterface(bytes4 interfaceId) external view returns (bool)
```
*See {IERC165-supportsInterface}.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| interfaceId | bytes4 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### tokenMapping
```solidity
function tokenMapping(address) external view returns (address)
```
Mapping from layer 2 token address to layer 1 token address for ERC1155 NFT.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### updateTokenMapping
```solidity
function updateTokenMapping(address _l2Token, address _l1Token) external nonpayable
```
Update layer 2 to layer 1 token mapping.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l2Token | address | The address of corresponding ERC1155 token on layer 2. |
| _l1Token | address | The address of ERC1155 token on layer 1. |
### withdrawERC1155
```solidity
function withdrawERC1155(address _token, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw some ERC1155 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC1155
```solidity
function withdrawERC1155(address _token, address _to, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw some ERC1155 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
## Events
### BatchWithdrawERC1155
```solidity
event BatchWithdrawERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds, uint256[] amounts)
```
Emitted when the ERC1155 NFT is batch transferred to gateway on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 2. |
| to | address | The address of recipient on layer 1. |
| tokenIds | uint256[] | The list of token ids of the ERC1155 NFT to withdraw on layer 2. |
| amounts | uint256[] | The list of corresponding amounts to withdraw. |
### FinalizeBatchDepositERC1155
```solidity
event FinalizeBatchDepositERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds, uint256[] amounts)
```
Emitted when the ERC1155 NFT is batch transferred to recipient on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 1. |
| to | address | The address of recipient on layer 2. |
| tokenIds | uint256[] | The list of token ids of the ERC1155 NFT deposited on layer 1. |
| amounts | uint256[] | The list of corresponding amounts deposited. |
### FinalizeDepositERC1155
```solidity
event FinalizeDepositERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId, uint256 amount)
```
Emitted when the ERC1155 NFT is transferred to recipient on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 1. |
| to | address | The address of recipient on layer 2. |
| tokenId | uint256 | The token id of the ERC1155 NFT deposited on layer 1. |
| amount | uint256 | The amount of token deposited. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token)
```
Emitted when token mapping for ERC1155 token is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l2Token `indexed` | address | The address of corresponding ERC1155 token in layer 2. |
| oldL1Token `indexed` | address | The address of the old corresponding ERC1155 token in layer 1. |
| newL1Token `indexed` | address | The address of the new corresponding ERC1155 token in layer 1. |
### WithdrawERC1155
```solidity
event WithdrawERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId, uint256 amount)
```
Emitted when the ERC1155 NFT is transferred to gateway on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC1155 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC1155 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 2. |
| to | address | The address of recipient on layer 1. |
| tokenId | uint256 | The token id of the ERC1155 NFT to withdraw on layer 2. |
| amount | uint256 | The amount of token to withdraw. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,486 +0,0 @@
# L2ERC721Gateway
> L2ERC721Gateway
The `L2ERC721Gateway` is used to withdraw ERC721 compatible NFTs on layer 2 and finalize deposit the NFTs from layer 1.
*The withdrawn NFTs tokens will be burned directly. On finalizing deposit, the corresponding NFT will be minted and transferred to the recipient. This will be changed if we have more specific scenarios.*
## Methods
### batchWithdrawERC721
```solidity
function batchWithdrawERC721(address _token, uint256[] _tokenIds, uint256 _gasLimit) external payable
```
Batch withdraw a list of ERC721 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _tokenIds | uint256[] | undefined |
| _gasLimit | uint256 | undefined |
### batchWithdrawERC721
```solidity
function batchWithdrawERC721(address _token, address _to, uint256[] _tokenIds, uint256 _gasLimit) external payable
```
Batch withdraw a list of ERC721 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| _gasLimit | uint256 | undefined |
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### finalizeBatchDepositERC721
```solidity
function finalizeBatchDepositERC721(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds) external nonpayable
```
Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC721Gateway on layer 1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
### finalizeDepositERC721
```solidity
function finalizeDepositERC721(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId) external nonpayable
```
Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC721Gateway on layer 1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _messenger) external nonpayable
```
Initialize the storage of `L2ERC721Gateway`.
*The parameters `_counterpart` and `_messenger` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of `L1ERC721Gateway` contract in L1. |
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### onERC721Received
```solidity
function onERC721Received(address, address, uint256, bytes) external nonpayable returns (bytes4)
```
*See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | bytes | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes4 | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### tokenMapping
```solidity
function tokenMapping(address) external view returns (address)
```
Mapping from layer 2 token address to layer 1 token address for ERC721 NFT.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### updateTokenMapping
```solidity
function updateTokenMapping(address _l2Token, address _l1Token) external nonpayable
```
Update layer 2 to layer 1 token mapping.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l2Token | address | The address of corresponding ERC721 token on layer 2. |
| _l1Token | address | The address of ERC721 token on layer 1. |
### withdrawERC721
```solidity
function withdrawERC721(address _token, uint256 _tokenId, uint256 _gasLimit) external payable
```
Withdraw some ERC721 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _tokenId | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC721
```solidity
function withdrawERC721(address _token, address _to, uint256 _tokenId, uint256 _gasLimit) external payable
```
Withdraw some ERC721 NFT to caller&#39;s account on layer 1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| _gasLimit | uint256 | undefined |
## Events
### BatchWithdrawERC721
```solidity
event BatchWithdrawERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds)
```
Emitted when the ERC721 NFT is batch transferred to gateway on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 2. |
| to | address | The address of recipient on layer 1. |
| tokenIds | uint256[] | The list of token ids of the ERC721 NFT to withdraw on layer 2. |
### FinalizeBatchDepositERC721
```solidity
event FinalizeBatchDepositERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds)
```
Emitted when the ERC721 NFT is batch transferred to recipient on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 1. |
| to | address | The address of recipient on layer 2. |
| tokenIds | uint256[] | The list of token ids of the ERC721 NFT deposited on layer 1. |
### FinalizeDepositERC721
```solidity
event FinalizeDepositERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId)
```
Emitted when the ERC721 NFT is transferred to recipient on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 1. |
| to | address | The address of recipient on layer 2. |
| tokenId | uint256 | The token id of the ERC721 NFT deposited on layer 1. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token)
```
Emitted when token mapping for ERC721 token is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l2Token `indexed` | address | The address of corresponding ERC721 token in layer 2. |
| oldL1Token `indexed` | address | The address of the old corresponding ERC721 token in layer 1. |
| newL1Token `indexed` | address | The address of the new corresponding ERC721 token in layer 1. |
### WithdrawERC721
```solidity
event WithdrawERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId)
```
Emitted when the ERC721 NFT is transferred to gateway on layer 2.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC721 NFT on layer 1. |
| l2Token `indexed` | address | The address of ERC721 NFT on layer 2. |
| from `indexed` | address | The address of sender on layer 2. |
| to | address | The address of recipient on layer 1. |
| tokenId | uint256 | The token id of the ERC721 NFT to withdraw on layer 2. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,566 +0,0 @@
# L2GatewayRouter
> L2GatewayRouter
The `L2GatewayRouter` is the main entry for withdrawing Ether and ERC20 tokens. All deposited tokens are routed to corresponding gateways.
*One can also use this contract to query L1/L2 token address mapping. In the future, ERC-721 and ERC-1155 tokens will be added to the router too.*
## Methods
### ERC20Gateway
```solidity
function ERC20Gateway(address) external view returns (address)
```
Mapping from L2 ERC20 token address to corresponding L2ERC20Gateway.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### defaultERC20Gateway
```solidity
function defaultERC20Gateway() external view returns (address)
```
The addess of default L2 ERC20 gateway, normally the L2StandardERC20Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### ethGateway
```solidity
function ethGateway() external view returns (address)
```
The address of L2ETHGateway.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### finalizeDepositERC20
```solidity
function finalizeDepositERC20(address, address, address, address, uint256, bytes) external payable
```
Complete a deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
*Make this function payable to handle WETH deposit/withdraw. The function should only be called by L2ScrollMessenger. The function should also only be called by L1ERC20Gateway in L1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | address | undefined |
| _3 | address | undefined |
| _4 | uint256 | undefined |
| _5 | bytes | undefined |
### finalizeDepositETH
```solidity
function finalizeDepositETH(address, address, uint256, bytes) external payable
```
Complete ETH deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
*This function should only be called by L2ScrollMessenger. This function should also only be called by L1GatewayRouter in L1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | bytes | undefined |
### getERC20Gateway
```solidity
function getERC20Gateway(address _token) external view returns (address)
```
Return the corresponding gateway address for given token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token to query. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### getL1ERC20Address
```solidity
function getL1ERC20Address(address _l2Address) external view returns (address)
```
Return the corresponding l1 token address given l2 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l2Address | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### getL2ERC20Address
```solidity
function getL2ERC20Address(address) external pure returns (address)
```
Return the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _ethGateway, address _defaultERC20Gateway) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _ethGateway | address | undefined |
| _defaultERC20Gateway | address | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### setDefaultERC20Gateway
```solidity
function setDefaultERC20Gateway(address _newDefaultERC20Gateway) external nonpayable
```
Update the address of default ERC20 gateway contract.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newDefaultERC20Gateway | address | The address to update. |
### setERC20Gateway
```solidity
function setERC20Gateway(address[] _tokens, address[] _gateways) external nonpayable
```
Update the mapping from token address to gateway address.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _tokens | address[] | The list of addresses of tokens to update. |
| _gateways | address[] | The list of addresses of gateways to update. |
### setETHGateway
```solidity
function setETHGateway(address _newEthGateway) external nonpayable
```
Update the address of ETH gateway contract.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newEthGateway | address | The address to update. |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### withdrawERC20
```solidity
function withdrawERC20(address _token, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw of some token to a caller&#39;s account on L1.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20
```solidity
function withdrawERC20(address _token, address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw of some token to a recipient&#39;s account on L1.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20AndCall
```solidity
function withdrawERC20AndCall(address _token, address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Withdraw of some token to a recipient&#39;s account on L1 and call.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
### withdrawETH
```solidity
function withdrawETH(address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw ETH to caller&#39;s account in L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawETH
```solidity
function withdrawETH(uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw ETH to caller&#39;s account in L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawETHAndCall
```solidity
function withdrawETHAndCall(address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Withdraw ETH to caller&#39;s account in L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
## Events
### FinalizeDepositERC20
```solidity
event FinalizeDepositERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when ERC20 token is deposited from L1 to L2 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L1. |
| to | address | The address of recipient in L2. |
| amount | uint256 | The amount of token withdrawn from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### FinalizeDepositETH
```solidity
event FinalizeDepositETH(address indexed from, address indexed to, uint256 amount, bytes data)
```
Emitted when ETH is deposited from L1 to L2 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| from `indexed` | address | The address of sender in L1. |
| to `indexed` | address | The address of recipient in L2. |
| amount | uint256 | The amount of ETH deposited from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### SetDefaultERC20Gateway
```solidity
event SetDefaultERC20Gateway(address indexed oldDefaultERC20Gateway, address indexed newDefaultERC20Gateway)
```
Emitted when the address of default ERC20 Gateway is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| oldDefaultERC20Gateway `indexed` | address | The address of the old default ERC20 Gateway. |
| newDefaultERC20Gateway `indexed` | address | The address of the new default ERC20 Gateway. |
### SetERC20Gateway
```solidity
event SetERC20Gateway(address indexed token, address indexed oldGateway, address indexed newGateway)
```
Emitted when the `gateway` for `token` is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | The address of token updated. |
| oldGateway `indexed` | address | The corresponding address of the old gateway. |
| newGateway `indexed` | address | The corresponding address of the new gateway. |
### SetETHGateway
```solidity
event SetETHGateway(address indexed oldETHGateway, address indexed newEthGateway)
```
Emitted when the address of ETH Gateway is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| oldETHGateway `indexed` | address | The address of the old ETH Gateway. |
| newEthGateway `indexed` | address | The address of the new ETH Gateway. |
### WithdrawERC20
```solidity
event WithdrawERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when someone withdraw ERC20 token from L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L2. |
| to | address | The address of recipient in L1. |
| amount | uint256 | The amount of token will be deposited from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
### WithdrawETH
```solidity
event WithdrawETH(address indexed from, address indexed to, uint256 amount, bytes data)
```
Emitted when someone withdraw ETH from L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| from `indexed` | address | The address of sender in L2. |
| to `indexed` | address | The address of recipient in L1. |
| amount | uint256 | The amount of ETH will be deposited from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |

View File

@@ -1,464 +0,0 @@
# L2ScrollMessenger
> L2ScrollMessenger
The `L2ScrollMessenger` contract can: 1. send messages from layer 2 to layer 1; 2. relay messages from layer 1 layer 2; 3. drop expired message due to sequencer problems.
*It should be a predeployed contract on layer 2 and should hold infinite amount of Ether (Specifically, `uint256(-1)`), which can be initialized in Genesis Block.*
## Methods
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of counterpart ScrollMessenger contract in L1/L2.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### feeVault
```solidity
function feeVault() external view returns (address)
```
The address of fee vault, collecting cross domain messaging fee.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### isL1MessageExecuted
```solidity
function isL1MessageExecuted(bytes32) external view returns (bool)
```
Mapping from L1 message hash to a boolean value indicating if the message has been successfully executed.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### messageQueue
```solidity
function messageQueue() external view returns (address)
```
The address of L2MessageQueue.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### messageSendTimestamp
```solidity
function messageSendTimestamp(bytes32) external view returns (uint256)
```
Mapping from L2 message hash to the timestamp when the message is sent.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### paused
```solidity
function paused() external view returns (bool)
```
*Returns true if the contract is paused, and false otherwise.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### relayMessage
```solidity
function relayMessage(address _from, address _to, uint256 _value, uint256 _nonce, bytes _message) external nonpayable
```
execute L1 =&gt; L2 message
*Make sure this is only called by privileged accounts.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### sendMessage
```solidity
function sendMessage(address _to, uint256 _value, bytes _message, uint256 _gasLimit, address) external payable
```
Send cross chain message from L1 to L2 or L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _value | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
| _4 | address | undefined |
### sendMessage
```solidity
function sendMessage(address _to, uint256 _value, bytes _message, uint256 _gasLimit) external payable
```
Send cross chain message from L1 to L2 or L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | undefined |
| _value | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
### setPause
```solidity
function setPause(bool _status) external nonpayable
```
Pause the contract
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _status | bool | The pause status to update. |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### updateFeeVault
```solidity
function updateFeeVault(address _newFeeVault) external nonpayable
```
Update fee vault contract.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newFeeVault | address | The address of new fee vault contract. |
### xDomainMessageSender
```solidity
function xDomainMessageSender() external view returns (address)
```
See {IScrollMessenger-xDomainMessageSender}
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
## Events
### FailedRelayedMessage
```solidity
event FailedRelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is failed to relay.
#### Parameters
| Name | Type | Description |
|---|---|---|
| messageHash `indexed` | bytes32 | The hash of the message. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### Paused
```solidity
event Paused(address account)
```
*Emitted when the pause is triggered by `account`.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| account | address | undefined |
### RelayedMessage
```solidity
event RelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is relayed successfully.
#### Parameters
| Name | Type | Description |
|---|---|---|
| messageHash `indexed` | bytes32 | The hash of the message. |
### SentMessage
```solidity
event SentMessage(address indexed sender, address indexed target, uint256 value, uint256 messageNonce, uint256 gasLimit, bytes message)
```
Emitted when a cross domain message is sent.
#### Parameters
| Name | Type | Description |
|---|---|---|
| sender `indexed` | address | The address of the sender who initiates the message. |
| target `indexed` | address | The address of target contract to call. |
| value | uint256 | The amount of value passed to the target contract. |
| messageNonce | uint256 | The nonce of the message. |
| gasLimit | uint256 | The optional gas limit passed to L1 or L2. |
| message | bytes | The calldata passed to the target contract. |
### Unpaused
```solidity
event Unpaused(address account)
```
*Emitted when the pause is lifted by `account`.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| account | address | undefined |
### UpdateFeeVault
```solidity
event UpdateFeeVault(address _oldFeeVault, address _newFeeVault)
```
Emitted when owner updates fee vault contract.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _oldFeeVault | address | The address of old fee vault contract. |
| _newFeeVault | address | The address of new fee vault contract. |
### UpdateMaxFailedExecutionTimes
```solidity
event UpdateMaxFailedExecutionTimes(uint256 oldMaxFailedExecutionTimes, uint256 newMaxFailedExecutionTimes)
```
Emitted when the maximum number of times each message can fail in L2 is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| oldMaxFailedExecutionTimes | uint256 | The old maximum number of times each message can fail in L2. |
| newMaxFailedExecutionTimes | uint256 | The new maximum number of times each message can fail in L2. |
## Errors
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,393 +0,0 @@
# L2StandardERC20Gateway
> L2StandardERC20Gateway
The `L2StandardERC20Gateway` is used to withdraw standard ERC20 tokens on layer 2 and finalize deposit the tokens from layer 1.
*The withdrawn ERC20 tokens will be burned directly. On finalizing deposit, the corresponding token will be minted and transferred to the recipient. Any ERC20 that requires non-standard functionality should use a separate gateway.*
## Methods
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### finalizeDepositERC20
```solidity
function finalizeDepositERC20(address _l1Token, address _l2Token, address _from, address _to, uint256 _amount, bytes _data) external payable
```
Complete a deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
*Make this function payable to handle WETH deposit/withdraw. The function should only be called by L2ScrollMessenger. The function should also only be called by L1ERC20Gateway in L1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
### getL1ERC20Address
```solidity
function getL1ERC20Address(address _l2Token) external view returns (address)
```
Return the corresponding l1 token address given l2 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l2Token | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### getL2ERC20Address
```solidity
function getL2ERC20Address(address _l1Token) external view returns (address)
```
Return the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _router, address _messenger, address) external nonpayable
```
Initialize the storage of L2StandardERC20Gateway.
*The parameters `_counterpart`, `_router`, `_messenger` and `_tokenFactory` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of `L1StandardERC20Gateway` contract in L1. |
| _router | address | The address of `L2GatewayRouter` contract in L2. |
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
| _3 | address | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### tokenFactory
```solidity
function tokenFactory() external view returns (address)
```
The address of ScrollStandardERC20Factory.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### withdrawERC20
```solidity
function withdrawERC20(address _token, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw of some token to a caller&#39;s account on L1.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20
```solidity
function withdrawERC20(address _token, address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw of some token to a recipient&#39;s account on L1.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20AndCall
```solidity
function withdrawERC20AndCall(address _token, address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Withdraw of some token to a recipient&#39;s account on L1 and call.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
## Events
### FinalizeDepositERC20
```solidity
event FinalizeDepositERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when ERC20 token is deposited from L1 to L2 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L1. |
| to | address | The address of recipient in L2. |
| amount | uint256 | The amount of token withdrawn from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### WithdrawERC20
```solidity
event WithdrawERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when someone withdraw ERC20 token from L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L2. |
| to | address | The address of recipient in L1. |
| amount | uint256 | The amount of token will be deposited from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

View File

@@ -1,409 +0,0 @@
# L2WETHGateway
> L2WETHGateway
The `L2WETHGateway` contract is used to withdraw `WETH` token on layer 2 and finalize deposit `WETH` from layer 1.
*The WETH tokens are not held in the gateway. It will first be unwrapped as Ether and then the Ether will be sent to the `L2ScrollMessenger` contract. On finalizing deposit, the Ether will be transferred from `L2ScrollMessenger`, then wrapped as WETH and finally transfer to recipient.*
## Methods
### WETH
```solidity
function WETH() external view returns (address)
```
The address of L2 WETH address.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### counterpart
```solidity
function counterpart() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### finalizeDepositERC20
```solidity
function finalizeDepositERC20(address _l1Token, address _l2Token, address _from, address _to, uint256 _amount, bytes _data) external payable
```
Complete a deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
*Make this function payable to handle WETH deposit/withdraw. The function should only be called by L2ScrollMessenger. The function should also only be called by L1ERC20Gateway in L1.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
### getL1ERC20Address
```solidity
function getL1ERC20Address(address) external view returns (address)
```
Return the corresponding l1 token address given l2 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### getL2ERC20Address
```solidity
function getL2ERC20Address(address) external view returns (address)
```
Return the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### initialize
```solidity
function initialize(address _counterpart, address _router, address _messenger) external nonpayable
```
Initialize the storage of `L2WETHGateway`.
*The parameters `_counterpart`, `_router` and `_messenger` are no longer used.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | The address of `L1WETHGateway` contract in L1. |
| _router | address | The address of `L2GatewayRouter` contract in L2. |
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
### l1WETH
```solidity
function l1WETH() external view returns (address)
```
The address of L1 WETH address.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
function router() external view returns (address)
```
The address of L1GatewayRouter/L2GatewayRouter contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### withdrawERC20
```solidity
function withdrawERC20(address _token, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw of some token to a caller&#39;s account on L1.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20
```solidity
function withdrawERC20(address _token, address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw of some token to a recipient&#39;s account on L1.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20AndCall
```solidity
function withdrawERC20AndCall(address _token, address _to, uint256 _amount, bytes _data, uint256 _gasLimit) external payable
```
Withdraw of some token to a recipient&#39;s account on L1 and call.
*Make this function payable to send relayer fee in Ether.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
## Events
### FinalizeDepositERC20
```solidity
event FinalizeDepositERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when ERC20 token is deposited from L1 to L2 and transfer to recipient.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L1. |
| to | address | The address of recipient in L2. |
| amount | uint256 | The amount of token withdrawn from L1 to L2. |
| data | bytes | The optional calldata passed to recipient in L2. |
### Initialized
```solidity
event Initialized(uint8 version)
```
*Triggered when the contract has been initialized or reinitialized.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### WithdrawERC20
```solidity
event WithdrawERC20(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data)
```
Emitted when someone withdraw ERC20 token from L2 to L1.
#### Parameters
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of the token in L1. |
| l2Token `indexed` | address | The address of the token in L2. |
| from `indexed` | address | The address of sender in L2. |
| to | address | The address of recipient in L1. |
| amount | uint256 | The amount of token will be deposited from L2 to L1. |
| data | bytes | The optional calldata passed to recipient in L1. |
## Errors
### ErrorCallerIsNotCounterpartGateway
```solidity
error ErrorCallerIsNotCounterpartGateway()
```
*Thrown when the cross chain sender is not the counterpart gateway contract.*
### ErrorCallerIsNotMessenger
```solidity
error ErrorCallerIsNotMessenger()
```
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
### ErrorNotInDropMessageContext
```solidity
error ErrorNotInDropMessageContext()
```
*Thrown when ScrollMessenger is not dropping message.*
### ErrorZeroAddress
```solidity
error ErrorZeroAddress()
```
*Thrown when the given address is `address(0)`.*

File diff suppressed because it is too large Load Diff

View File

@@ -1,159 +0,0 @@
# ScrollStandardERC20Factory
> ScrollStandardERC20Factory
The `ScrollStandardERC20Factory` is used to deploy `ScrollStandardERC20` for `L2StandardERC20Gateway`. It uses the `Clones` contract to deploy contract with minimum gas usage.
*The implementation of deployed token is non-upgradable. This design may be changed in the future.*
## Methods
### computeL2TokenAddress
```solidity
function computeL2TokenAddress(address _gateway, address _l1Token) external view returns (address)
```
Compute the corresponding l2 token address given l1 token address.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _gateway | address | The address of gateway contract. |
| _l1Token | address | The address of l1 token. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### deployL2Token
```solidity
function deployL2Token(address _gateway, address _l1Token) external nonpayable returns (address)
```
Deploy the corresponding l2 token address given l1 token address.
*This function should only be called by owner to avoid DDoS attack on StandardTokenBridge.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _gateway | address | The address of gateway contract. |
| _l1Token | address | The address of l1 token. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### implementation
```solidity
function implementation() external view returns (address)
```
The address of `ScrollStandardERC20` implementation.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
## Events
### DeployToken
```solidity
event DeployToken(address indexed _l1Token, address indexed _l2Token)
```
Emitted when a l2 token is deployed.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | The address of the l1 token. |
| _l2Token `indexed` | address | The address of the l2 token. |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |

View File

@@ -1,30 +0,0 @@
[profile.default]
src = 'src' # the source directory
test = 'src/test' # the test directory
script = 'scripts' # the script directory
out = 'artifacts/src' # the output directory (for artifacts)
libs = [] # a list of library directories
remappings = [] # a list of remappings
libraries = [] # a list of deployed libraries to link against
cache = true # whether to cache builds or not
force = true # whether to ignore the cache (clean build)
evm_version = 'cancun' # the evm version (by hardfork name)
solc_version = '0.8.24' # override for the solc version (setting this ignores `auto_detect_solc`)
optimizer = true # enable or disable the solc optimizer
optimizer_runs = 200 # the number of optimizer runs
verbosity = 2 # the verbosity of tests
ignored_error_codes = [] # a list of ignored solc error codes
fuzz_runs = 256 # the number of fuzz runs for tests
ffi = false # whether to enable ffi or not
sender = '0x00a329c0648769a73afac7f9381e08fb43dbea72' # the address of `msg.sender` in tests
tx_origin = '0x00a329c0648769a73afac7f9381e08fb43dbea72' # the address of `tx.origin` in tests
initial_balance = '0xffffffffffffffffffffffff' # the initial balance of the test contract
block_number = 0 # the block number we are at in tests
gas_limit = 9223372036854775807 # the gas limit in tests
gas_price = 0 # the gas price (in wei) in tests
block_base_fee_per_gas = 0 # the base fee (in wei) in tests
block_coinbase = '0x0000000000000000000000000000000000000000' # the address of `block.coinbase` in tests
block_timestamp = 0 # the value of `block.timestamp` in tests
block_difficulty = 0 # the value of `block.difficulty` in tests
gas_reports = ["L2GasPriceOracle"]

View File

@@ -1,10 +0,0 @@
{
"blockHash": "0x3e721eda79f26bf40cd915aad0c85d501849215ad907d2e38acff524847300ab",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFee": "0x3b9aca00",
"stateRoot": "0x183cbfdab83f8884b7cfbe234cb99bbd654d4fb18bd9c9f01e94ebf859957739",
"blockHeight": 0,
"gasUsed": 0,
"timestamp": "0x61bc34a0",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000004cb1ab63af5d8931ce09673ebd8ae2ce16fd6571adf5218f7ca8c80d90ff63af5fef486af57c20960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}

View File

@@ -1,151 +0,0 @@
import * as dotenv from "dotenv";
import { HardhatUserConfig, subtask } from "hardhat/config";
import * as toml from "toml";
import "@nomicfoundation/hardhat-verify";
import "@nomicfoundation/hardhat-ethers";
import "@nomicfoundation/hardhat-chai-matchers";
import "@typechain/hardhat";
import "@primitivefi/hardhat-dodoc";
import "hardhat-gas-reporter";
import "solidity-coverage";
import { readFileSync } from "fs";
import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from "hardhat/builtin-tasks/task-names";
dotenv.config();
const L1_DEPLOYER_PRIVATE_KEY = process.env.L1_DEPLOYER_PRIVATE_KEY || "1".repeat(64);
const L2_DEPLOYER_PRIVATE_KEY = process.env.L2_DEPLOYER_PRIVATE_KEY || "1".repeat(64);
const SOLC_DEFAULT = "0.8.24";
// try use forge config
let foundry: any;
try {
foundry = toml.parse(readFileSync("./foundry.toml").toString());
foundry.default.solc = foundry.default["solc-version"] ? foundry.default["solc-version"] : SOLC_DEFAULT;
} catch (error) {
foundry = {
default: {
solc: SOLC_DEFAULT,
},
};
}
// prune forge style tests from hardhat paths
subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(async (_, __, runSuper) => {
const paths = await runSuper();
return paths.filter((p: string) => !p.endsWith(".t.sol")).filter((p: string) => !p.includes("test/mocks"));
});
const config: HardhatUserConfig = {
solidity: {
version: foundry.default?.solc_version || SOLC_DEFAULT,
settings: {
optimizer: {
enabled: foundry.default?.optimizer || true,
runs: foundry.default?.optimizer_runs || 200,
},
evmVersion: "cancun",
},
},
networks: {
ethereum: {
url: "https://1rpc.io/eth",
accounts: [L1_DEPLOYER_PRIVATE_KEY],
},
sepolia: {
url: "https://1rpc.io/sepolia",
accounts: [L1_DEPLOYER_PRIVATE_KEY],
},
scroll: {
url: "https://rpc.scroll.io",
accounts: [L2_DEPLOYER_PRIVATE_KEY],
},
scroll_sepolia: {
url: "https://sepolia-rpc.scroll.io",
accounts: [L2_DEPLOYER_PRIVATE_KEY],
},
},
paths: {
cache: "./cache-hardhat",
sources: "./src",
tests: "./integration-test",
},
typechain: {
outDir: "./typechain",
target: "ethers-v6",
},
gasReporter: {
enabled: process.env.REPORT_GAS !== undefined,
excludeContracts: ["src/test"],
currency: "USD",
},
etherscan: {
apiKey: {
ethereum: process.env.ETHERSCAN_API_KEY || "",
sepolia: process.env.ETHERSCAN_API_KEY || "",
scroll: process.env.SCROLLSCAN_API_KEY || "",
scroll_sepolia: process.env.SCROLLSCAN_API_KEY || "",
},
customChains: [
{
network: "scroll",
chainId: 534352,
urls: {
apiURL: "https://api.scrollscan.com/api",
browserURL: "https://www.scrollscan.com/",
},
},
{
network: "scroll_sepolia",
chainId: 534351,
urls: {
apiURL: "https://api-sepolia.scrollscan.com/api",
browserURL: "https://sepolia.scrollscan.com/",
},
},
],
},
mocha: {
timeout: 10000000,
},
dodoc: {
runOnCompile: true,
keepFileStructure: false,
include: [
"ScrollChain",
"L1ScrollMessenger",
"L2ScrollMessenger",
"L1GatewayRouter",
"L2GatewayRouter",
"L1StandardERC20Gateway",
"L2StandardERC20Gateway",
"L1ERC721Gateway",
"L2ERC721Gateway",
"L1ERC1155Gateway",
"L2ERC1155Gateway",
"L1WETHGateway",
"L2WETHGateway",
"ScrollStandardERC20Factory",
],
outputDir: "docs/apis",
exclude: [
"IERC677Receiver",
"IL1ScrollMessenger",
"IL2ScrollMessenger",
"IL1GatewayRouter",
"IL2GatewayRouter",
"IL1ERC721Gateway",
"IL2ERC721Gateway",
"IL1ERC1155Gateway",
"IL2ERC1155Gateway",
"IScrollStandardERC20Factory",
"IScrollChain",
"ScrollChainCommitmentVerifier",
"WETH9",
],
},
};
export default config;

View File

@@ -1,455 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { HardhatEthersSigner, SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { BigNumberish, BytesLike, MaxUint256, ZeroAddress, getBytes } from "ethers";
import { ethers } from "hardhat";
import { EnforcedTxGateway, L1MessageQueue, L2GasPriceOracle, MockCaller } from "../typechain";
describe("EnforcedTxGateway.spec", async () => {
let deployer: HardhatEthersSigner;
let feeVault: HardhatEthersSigner;
let signer: HardhatEthersSigner;
let caller: MockCaller;
let gateway: EnforcedTxGateway;
let oracle: L2GasPriceOracle;
let queue: L1MessageQueue;
const deployProxy = async (name: string, admin: string, args: any[]): Promise<string> => {
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const Factory = await ethers.getContractFactory(name, deployer);
const impl = args.length > 0 ? await Factory.deploy(...args) : await Factory.deploy();
const proxy = await TransparentUpgradeableProxy.deploy(impl.getAddress(), admin, "0x");
return proxy.getAddress();
};
beforeEach(async () => {
[deployer, feeVault, signer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
const admin = await ProxyAdmin.deploy();
gateway = await ethers.getContractAt(
"EnforcedTxGateway",
await deployProxy("EnforcedTxGateway", await admin.getAddress(), []),
deployer
);
queue = await ethers.getContractAt(
"L1MessageQueue",
await deployProxy("L1MessageQueue", await admin.getAddress(), [
deployer.address,
deployer.address,
await gateway.getAddress(),
]),
deployer
);
oracle = await ethers.getContractAt(
"L2GasPriceOracle",
await deployProxy("L2GasPriceOracle", await admin.getAddress(), []),
deployer
);
const MockCaller = await ethers.getContractFactory("MockCaller", deployer);
caller = await MockCaller.deploy();
await queue.initialize(ZeroAddress, ZeroAddress, ZeroAddress, oracle.getAddress(), 10000000);
await gateway.initialize(queue.getAddress(), feeVault.address);
await oracle.initialize(21000, 51000, 8, 16);
const Whitelist = await ethers.getContractFactory("Whitelist", deployer);
const whitelist = await Whitelist.deploy(deployer.address);
await whitelist.updateWhitelistStatus([deployer.address], true);
await oracle.updateWhitelist(whitelist.getAddress());
await oracle.setL2BaseFee(1);
});
context("auth", async () => {
it("should initialize correctly", async () => {
expect(await gateway.owner()).to.eq(deployer.address);
expect(await gateway.messageQueue()).to.eq(await queue.getAddress());
expect(await gateway.feeVault()).to.eq(feeVault.address);
expect(await gateway.paused()).to.eq(false);
});
it("should revert, when initialize again", async () => {
await expect(gateway.initialize(ZeroAddress, ZeroAddress)).to.revertedWith(
"Initializable: contract is already initialized"
);
});
context("#updateFeeVault", async () => {
it("should revert, when non-owner call", async () => {
await expect(gateway.connect(signer).updateFeeVault(ZeroAddress)).to.revertedWith(
"Ownable: caller is not the owner"
);
});
it("should succeed", async () => {
expect(await gateway.feeVault()).to.eq(feeVault.address);
await expect(gateway.updateFeeVault(deployer.address))
.to.emit(gateway, "UpdateFeeVault")
.withArgs(feeVault.address, deployer.address);
expect(await gateway.feeVault()).to.eq(deployer.address);
});
});
context("#setPause", async () => {
it("should revert, when non-owner call", async () => {
await expect(gateway.connect(signer).setPause(false)).to.revertedWith("Ownable: caller is not the owner");
});
it("should succeed", async () => {
expect(await gateway.paused()).to.eq(false);
await expect(gateway.setPause(true)).to.emit(gateway, "Paused").withArgs(deployer.address);
expect(await gateway.paused()).to.eq(true);
await expect(gateway.setPause(false)).to.emit(gateway, "Unpaused").withArgs(deployer.address);
expect(await gateway.paused()).to.eq(false);
});
});
});
context("#sendTransaction, by EOA", async () => {
it("should revert, when contract is paused", async () => {
await gateway.setPause(true);
await expect(
gateway.connect(signer)["sendTransaction(address,uint256,uint256,bytes)"](signer.address, 0, 0, "0x")
).to.revertedWith("Pausable: paused");
});
it("should revert, when call is not EOA", async () => {
const calldata = gateway.interface.encodeFunctionData("sendTransaction(address,uint256,uint256,bytes)", [
signer.address,
0,
0,
"0x",
]);
await expect(caller.callTarget(gateway.getAddress(), calldata)).to.revertedWith(
"Only EOA senders are allowed to send enforced transaction"
);
});
it("should revert, when insufficient value for fee", async () => {
const fee = await queue.estimateCrossDomainMessageFee(1000000);
await expect(
gateway
.connect(signer)
["sendTransaction(address,uint256,uint256,bytes)"](signer.address, 0, 1000000, "0x", { value: fee - 1n })
).to.revertedWith("Insufficient value for fee");
});
it("should revert, when failed to deduct the fee", async () => {
await gateway.updateFeeVault(gateway.getAddress());
const fee = await queue.estimateCrossDomainMessageFee(1000000);
await expect(
gateway
.connect(signer)
["sendTransaction(address,uint256,uint256,bytes)"](signer.address, 0, 1000000, "0x", { value: fee })
).to.revertedWith("Failed to deduct the fee");
});
it("should succeed, no refund", async () => {
const fee = await queue.estimateCrossDomainMessageFee(1000000);
const feeVaultBalanceBefore = await ethers.provider.getBalance(feeVault.address);
await expect(
gateway
.connect(signer)
["sendTransaction(address,uint256,uint256,bytes)"](deployer.address, 0, 1000000, "0x", { value: fee })
)
.to.emit(queue, "QueueTransaction")
.withArgs(signer.address, deployer.address, 0, 0, 1000000, "0x");
const feeVaultBalanceAfter = await ethers.provider.getBalance(feeVault.address);
expect(feeVaultBalanceAfter - feeVaultBalanceBefore).to.eq(fee);
});
it("should succeed, with refund", async () => {
const fee = await queue.estimateCrossDomainMessageFee(1000000);
const feeVaultBalanceBefore = await ethers.provider.getBalance(feeVault.address);
const signerBalanceBefore = await ethers.provider.getBalance(signer.address);
const tx = await gateway
.connect(signer)
["sendTransaction(address,uint256,uint256,bytes)"](deployer.address, 0, 1000000, "0x", { value: fee + 100n });
await expect(tx)
.to.emit(queue, "QueueTransaction")
.withArgs(signer.address, deployer.address, 0, 0, 1000000, "0x");
const receipt = await tx.wait();
const feeVaultBalanceAfter = await ethers.provider.getBalance(feeVault.address);
const signerBalanceAfter = await ethers.provider.getBalance(signer.address);
expect(feeVaultBalanceAfter - feeVaultBalanceBefore).to.eq(fee);
expect(signerBalanceBefore - signerBalanceAfter).to.eq(receipt!.gasUsed * receipt!.gasPrice + fee);
});
});
context("#sendTransaction, with signatures", async () => {
const getSignature = async (
signer: SignerWithAddress,
target: string,
value: BigNumberish,
gasLimit: BigNumberish,
data: BytesLike
) => {
const enforcedTx = {
sender: signer.address,
target,
value,
gasLimit,
data: getBytes(data),
nonce: await gateway.nonces(signer.address),
deadline: MaxUint256,
};
const domain = {
name: "EnforcedTxGateway",
version: "1",
chainId: (await ethers.provider.getNetwork()).chainId,
verifyingContract: await gateway.getAddress(),
};
const types = {
EnforcedTransaction: [
{
name: "sender",
type: "address",
},
{
name: "target",
type: "address",
},
{
name: "value",
type: "uint256",
},
{
name: "gasLimit",
type: "uint256",
},
{
name: "data",
type: "bytes",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
type: "uint256",
},
],
};
const signature = await signer.signTypedData(domain, types, enforcedTx);
return signature;
};
it("should revert, when contract is paused", async () => {
await gateway.setPause(true);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
0,
"0x",
MaxUint256,
"0x",
ZeroAddress
)
).to.revertedWith("Pausable: paused");
});
it("should revert, when signature expired", async () => {
const timestamp = (await ethers.provider.getBlock("latest"))!.timestamp;
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
0,
"0x",
timestamp - 1,
"0x",
ZeroAddress
)
).to.revertedWith("signature expired");
});
it("should revert, when signature is wrong", async () => {
const signature = await signer.signMessage("0x00");
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
0,
"0x",
MaxUint256,
signature,
ZeroAddress
)
).to.revertedWith("Incorrect signature");
});
it("should revert, when insufficient value for fee", async () => {
const signature = await getSignature(signer, signer.address, 0, 1000000, "0x");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
1000000,
"0x",
MaxUint256,
signature,
signer.address,
{ value: fee - 1n }
)
).to.revertedWith("Insufficient value for fee");
});
it("should revert, when failed to deduct the fee", async () => {
await gateway.updateFeeVault(gateway.getAddress());
const signature = await getSignature(signer, signer.address, 0, 1000000, "0x");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
1000000,
"0x",
MaxUint256,
signature,
signer.address,
{ value: fee }
)
).to.revertedWith("Failed to deduct the fee");
});
it("should succeed, no refund", async () => {
const signature = await getSignature(signer, deployer.address, 0, 1000000, "0x");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
const feeVaultBalanceBefore = await ethers.provider.getBalance(feeVault.address);
expect(await gateway.nonces(signer.address)).to.eq(0);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
MaxUint256,
signature,
signer.address,
{ value: fee }
)
)
.to.emit(queue, "QueueTransaction")
.withArgs(signer.address, deployer.address, 0, 0, 1000000, "0x");
expect(await gateway.nonces(signer.address)).to.eq(1);
const feeVaultBalanceAfter = await ethers.provider.getBalance(feeVault.address);
expect(feeVaultBalanceAfter - feeVaultBalanceBefore).to.eq(fee);
// use the same nonce to sign should fail
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
MaxUint256,
signature,
signer.address,
{ value: fee }
)
).to.revertedWith("Incorrect signature");
});
it("should succeed, with refund", async () => {
const signature = await getSignature(signer, deployer.address, 0, 1000000, "0x");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
const feeVaultBalanceBefore = await ethers.provider.getBalance(feeVault.address);
const signerBalanceBefore = await ethers.provider.getBalance(signer.address);
expect(await gateway.nonces(signer.address)).to.eq(0);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
MaxUint256,
signature,
signer.address,
{ value: fee + 100n }
)
)
.to.emit(queue, "QueueTransaction")
.withArgs(signer.address, deployer.address, 0, 0, 1000000, "0x");
expect(await gateway.nonces(signer.address)).to.eq(1);
const feeVaultBalanceAfter = await ethers.provider.getBalance(feeVault.address);
const signerBalanceAfter = await ethers.provider.getBalance(signer.address);
expect(feeVaultBalanceAfter - feeVaultBalanceBefore).to.eq(fee);
expect(signerBalanceAfter - signerBalanceBefore).to.eq(100n);
// use the same nonce to sign should fail
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
MaxUint256,
signature,
signer.address,
{ value: fee + 100n }
)
).to.revertedWith("Incorrect signature");
});
it("should revert, when refund failed", async () => {
const signature = await getSignature(signer, signer.address, 0, 1000000, "0x1234");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
1000000,
"0x1234",
MaxUint256,
signature,
gateway.getAddress(),
{ value: fee + 100n }
)
).to.revertedWith("Failed to refund the fee");
});
});
});

View File

@@ -1,661 +0,0 @@
/* eslint-disable node/no-missing-import */
/* eslint-disable node/no-unpublished-import */
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { BigNumberish, ContractTransactionResponse, MaxUint256, keccak256, toQuantity } from "ethers";
import { ethers, network } from "hardhat";
import {
ProxyAdmin,
L1GatewayRouter,
L2ScrollMessenger,
L1ScrollMessenger,
L1MessageQueueWithGasPriceOracle,
L2GatewayRouter,
} from "../typechain";
describe("GasOptimizationUpgrade.spec", async () => {
const L1_ROUTER = "0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6";
const L2_ROUTER = "0x4C0926FF5252A435FD19e10ED15e5a249Ba19d79";
const L1_MESSENGER = "0x6774Bcbd5ceCeF1336b5300fb5186a12DDD8b367";
const L2_MESSENGER = "0x781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC";
const L1_MESSAGE_QUEUE = "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B";
const L2_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000";
const SCROLL_CHAIN = "0xa13BAF47339d63B743e7Da8741db5456DAc1E556";
let deployer: HardhatEthersSigner;
let proxyAdmin: ProxyAdmin;
const mockERC20Balance = async (tokenAddress: string, balance: bigint, slot: BigNumberish) => {
const storageSlot = keccak256(
ethers.AbiCoder.defaultAbiCoder().encode(["address", "uint256"], [deployer.address, slot])
);
await ethers.provider.send("hardhat_setStorageAt", [tokenAddress, storageSlot, toQuantity(balance)]);
const token = await ethers.getContractAt("MockERC20", tokenAddress, deployer);
expect(await token.balanceOf(deployer.address)).to.eq(balance);
};
const mockETHBalance = async (balance: bigint) => {
await network.provider.send("hardhat_setBalance", [deployer.address, toQuantity(balance)]);
expect(await ethers.provider.getBalance(deployer.address)).to.eq(balance);
};
const showGasUsage = async (tx: ContractTransactionResponse, desc: string) => {
const receipt = await tx.wait();
console.log(`${desc}: GasUsed[${receipt!.gasUsed}]`);
};
context("L1 upgrade", async () => {
let forkBlock: number;
let router: L1GatewayRouter;
let messenger: L1ScrollMessenger;
let queue: L1MessageQueueWithGasPriceOracle;
beforeEach(async () => {
// fork network
const provider = new ethers.JsonRpcProvider("https://rpc.ankr.com/eth");
if (!forkBlock) {
forkBlock = (await provider.getBlockNumber()) - 10;
}
await network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: "https://rpc.ankr.com/eth",
blockNumber: forkBlock,
},
},
],
});
await network.provider.request({
method: "hardhat_impersonateAccount",
params: ["0x1100000000000000000000000000000000000011"],
});
// mock eth balance
deployer = await ethers.getSigner("0x1100000000000000000000000000000000000011");
await mockETHBalance(ethers.parseEther("1000"));
// mock owner of proxy admin
proxyAdmin = await ethers.getContractAt("ProxyAdmin", "0xEB803eb3F501998126bf37bB823646Ed3D59d072", deployer);
await ethers.provider.send("hardhat_setStorageAt", [
await proxyAdmin.getAddress(),
"0x0",
ethers.AbiCoder.defaultAbiCoder().encode(["address"], [deployer.address]),
]);
expect(await proxyAdmin.owner()).to.eq(deployer.address);
router = await ethers.getContractAt("L1GatewayRouter", L1_ROUTER, deployer);
messenger = await ethers.getContractAt("L1ScrollMessenger", L1_MESSENGER, deployer);
queue = await ethers.getContractAt("L1MessageQueueWithGasPriceOracle", L1_MESSAGE_QUEUE, deployer);
});
const upgradeL1 = async (proxy: string, impl: string) => {
await proxyAdmin.upgrade(proxy, impl);
const L1ScrollMessenger = await ethers.getContractFactory("L1ScrollMessenger", deployer);
const L1MessageQueueWithGasPriceOracle = await ethers.getContractFactory(
"L1MessageQueueWithGasPriceOracle",
deployer
);
const ScrollChain = await ethers.getContractFactory("ScrollChain", deployer);
await proxyAdmin.upgrade(
L1_MESSENGER,
(await L1ScrollMessenger.deploy(L2_MESSENGER, SCROLL_CHAIN, L1_MESSAGE_QUEUE)).getAddress()
);
await proxyAdmin.upgrade(
L1_MESSAGE_QUEUE,
(
await L1MessageQueueWithGasPriceOracle.deploy(
L1_MESSENGER,
SCROLL_CHAIN,
"0x72CAcBcfDe2d1e19122F8A36a4d6676cd39d7A5d"
)
).getAddress()
);
await queue.initializeV2();
await proxyAdmin.upgrade(
SCROLL_CHAIN,
(await ScrollChain.deploy(534352, L1_MESSAGE_QUEUE, "0xA2Ab526e5C5491F10FC05A55F064BF9F7CEf32a0")).getAddress()
);
};
it.skip("should succeed on L1ETHGateway", async () => {
const L1_GATEWAY = "0x7F2b8C31F88B6006c382775eea88297Ec1e3E905";
const L2_GATEWAY = "0x6EA73e05AdC79974B931123675ea8F78FfdacDF0";
const L1ETHGateway = await ethers.getContractFactory("L1ETHGateway", deployer);
const impl = await L1ETHGateway.deploy(L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
const gateway = await ethers.getContractAt("L1ETHGateway", L1_GATEWAY, deployer);
const amountIn = ethers.parseEther("1");
const fee = await queue.estimateCrossDomainMessageFee(1e6);
// before upgrade
await showGasUsage(
await gateway["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn + fee }),
"L1ETHGateway.depositETH before upgrade"
);
await showGasUsage(
await router["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn + fee }),
"L1GatewayRouter.depositETH before upgrade"
);
await showGasUsage(
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
value: amountIn + fee,
}),
"L1ScrollMessenger.sendMessage before upgrade"
);
// do upgrade
await upgradeL1(L1_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn + fee }),
"L1ETHGateway.depositETH after upgrade"
);
await showGasUsage(
await router["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn + fee }),
"L1GatewayRouter.depositETH after upgrade"
);
await showGasUsage(
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
value: amountIn + fee,
}),
"L1ScrollMessenger.sendMessage after upgrade"
);
});
it.skip("should succeed on L1WETHGateway", async () => {
const L1_WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const L2_WETH = "0x5300000000000000000000000000000000000004";
const L1_GATEWAY = "0x7AC440cAe8EB6328de4fA621163a792c1EA9D4fE";
const L2_GATEWAY = "0x7003E7B7186f0E6601203b99F7B8DECBfA391cf9";
const L1WETHGateway = await ethers.getContractFactory("L1WETHGateway", deployer);
const impl = await L1WETHGateway.deploy(L1_WETH, L2_WETH, L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
const gateway = await ethers.getContractAt("L1WETHGateway", L1_GATEWAY, deployer);
const amountIn = ethers.parseEther("1");
const fee = await queue.estimateCrossDomainMessageFee(1e6);
const token = await ethers.getContractAt("MockERC20", L1_WETH, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 3);
await token.approve(L1_GATEWAY, MaxUint256);
await token.approve(L1_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
"L1WETHGateway.depositERC20 WETH before upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 WETH before upgrade"
);
// do upgrade
await upgradeL1(L1_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
"L1WETHGateway.depositERC20 WETH after upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 WETH after upgrade"
);
});
it.skip("should succeed on L1StandardERC20Gateway", async () => {
const L1_USDT = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
const L1_GATEWAY = "0xD8A791fE2bE73eb6E6cF1eb0cb3F36adC9B3F8f9";
const L2_GATEWAY = "0xE2b4795039517653c5Ae8C2A9BFdd783b48f447A";
const L1StandardERC20Gateway = await ethers.getContractFactory("L1StandardERC20Gateway", deployer);
const impl = await L1StandardERC20Gateway.deploy(
L2_GATEWAY,
L1_ROUTER,
L1_MESSENGER,
"0xC7d86908ccf644Db7C69437D5852CedBC1aD3f69",
"0x66e5312EDeEAef6e80759A0F789e7914Fb401484"
);
const gateway = await ethers.getContractAt("L1StandardERC20Gateway", L1_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 6);
const fee = await queue.estimateCrossDomainMessageFee(1e6);
const token = await ethers.getContractAt("MockERC20", L1_USDT, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 2);
await token.approve(L1_GATEWAY, MaxUint256);
await token.approve(L1_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
"L1StandardERC20Gateway.depositERC20 USDT before upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 USDT before upgrade"
);
// do upgrade
await upgradeL1(L1_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
"L1StandardERC20Gateway.depositERC20 USDT after upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 USDT after upgrade"
);
});
it.skip("should succeed on L1CustomERC20Gateway", async () => {
const L1_DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
const L1_GATEWAY = "0x67260A8B73C5B77B55c1805218A42A7A6F98F515";
const L2_GATEWAY = "0xaC78dff3A87b5b534e366A93E785a0ce8fA6Cc62";
const L1CustomERC20Gateway = await ethers.getContractFactory("L1CustomERC20Gateway", deployer);
const impl = await L1CustomERC20Gateway.deploy(L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
const gateway = await ethers.getContractAt("L1CustomERC20Gateway", L1_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 18);
const fee = await queue.estimateCrossDomainMessageFee(1e6);
const token = await ethers.getContractAt("MockERC20", L1_DAI, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 2);
await token.approve(L1_GATEWAY, MaxUint256);
await token.approve(L1_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
"L1CustomERC20Gateway.depositERC20 DAI before upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 DAI before upgrade"
);
// do upgrade
await upgradeL1(L1_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
"L1CustomERC20Gateway.depositERC20 DAI after upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 DAI after upgrade"
);
});
it.skip("should succeed on L1USDCGateway", async () => {
const L1_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const L2_USDC = "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4";
const L1_GATEWAY = "0xf1AF3b23DE0A5Ca3CAb7261cb0061C0D779A5c7B";
const L2_GATEWAY = "0x33B60d5Dd260d453cAC3782b0bDC01ce84672142";
const L1USDCGateway = await ethers.getContractFactory("L1USDCGateway", deployer);
const impl = await L1USDCGateway.deploy(L1_USDC, L2_USDC, L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
const gateway = await ethers.getContractAt("L1USDCGateway", L1_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 6);
const fee = await queue.estimateCrossDomainMessageFee(1e6);
const token = await ethers.getContractAt("MockERC20", L1_USDC, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 9);
await token.approve(L1_GATEWAY, MaxUint256);
await token.approve(L1_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
"L1USDCGateway.depositERC20 USDC before upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 USDC before upgrade"
);
// do upgrade
await upgradeL1(L1_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
"L1USDCGateway.depositERC20 USDC after upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 USDC after upgrade"
);
});
it.skip("should succeed on L1LidoGateway", async () => {
const L1_WSTETH = "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0";
const L2_WSTETH = "0xf610A9dfB7C89644979b4A0f27063E9e7d7Cda32";
const L1_GATEWAY = "0x6625C6332c9F91F2D27c304E729B86db87A3f504";
const L2_GATEWAY = "0x8aE8f22226B9d789A36AC81474e633f8bE2856c9";
const L1LidoGateway = await ethers.getContractFactory("L1LidoGateway", deployer);
const impl = await L1LidoGateway.deploy(L1_WSTETH, L2_WSTETH, L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
const gateway = await ethers.getContractAt("L1LidoGateway", L1_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 6);
const fee = await queue.estimateCrossDomainMessageFee(1e6);
const token = await ethers.getContractAt("MockERC20", L1_WSTETH, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 0);
await token.approve(L1_GATEWAY, MaxUint256);
await token.approve(L1_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_WSTETH, amountIn, 1e6, { value: fee }),
"L1LidoGateway.depositERC20 wstETH before upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_WSTETH, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 wstETH before upgrade"
);
// do upgrade
await upgradeL1(L1_GATEWAY, await impl.getAddress());
await gateway.initializeV2(deployer.address, deployer.address, deployer.address, deployer.address);
// after upgrade
await showGasUsage(
await gateway["depositERC20(address,uint256,uint256)"](L1_WSTETH, amountIn, 1e6, { value: fee }),
"L1LidoGateway.depositERC20 wstETH after upgrade"
);
await showGasUsage(
await router["depositERC20(address,uint256,uint256)"](L1_WSTETH, amountIn, 1e6, { value: fee }),
"L1GatewayRouter.depositERC20 wstETH after upgrade"
);
});
});
context("L2 upgrade", async () => {
let forkBlock: number;
let router: L2GatewayRouter;
let messenger: L2ScrollMessenger;
beforeEach(async () => {
// fork network
const provider = new ethers.JsonRpcProvider("https://rpc.scroll.io");
if (!forkBlock) {
forkBlock = (await provider.getBlockNumber()) - 31;
}
await network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: "https://rpc.scroll.io",
blockNumber: forkBlock,
},
},
],
});
await network.provider.request({
method: "hardhat_impersonateAccount",
params: ["0x1100000000000000000000000000000000000011"],
});
// mock eth balance
deployer = await ethers.getSigner("0x1100000000000000000000000000000000000011");
await mockETHBalance(ethers.parseEther("1000"));
// mock owner of proxy admin
proxyAdmin = await ethers.getContractAt("ProxyAdmin", "0xA76acF000C890b0DD7AEEf57627d9899F955d026", deployer);
await ethers.provider.send("hardhat_setStorageAt", [
await proxyAdmin.getAddress(),
"0x0",
ethers.AbiCoder.defaultAbiCoder().encode(["address"], [deployer.address]),
]);
expect(await proxyAdmin.owner()).to.eq(deployer.address);
router = await ethers.getContractAt("L2GatewayRouter", L2_ROUTER, deployer);
messenger = await ethers.getContractAt("L2ScrollMessenger", L2_MESSENGER, deployer);
});
const upgradeL2 = async (proxy: string, impl: string) => {
await proxyAdmin.upgrade(proxy, impl);
const L2ScrollMessenger = await ethers.getContractFactory("L2ScrollMessenger", deployer);
await proxyAdmin.upgrade(
L2_MESSENGER,
(await L2ScrollMessenger.deploy(L1_MESSENGER, L2_MESSAGE_QUEUE)).getAddress()
);
};
it.skip("should succeed on L2ETHGateway", async () => {
const L1_GATEWAY = "0x7F2b8C31F88B6006c382775eea88297Ec1e3E905";
const L2_GATEWAY = "0x6EA73e05AdC79974B931123675ea8F78FfdacDF0";
const L2ETHGateway = await ethers.getContractFactory("L2ETHGateway", deployer);
const impl = await L2ETHGateway.deploy(L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
const gateway = await ethers.getContractAt("L2ETHGateway", L2_GATEWAY, deployer);
const amountIn = ethers.parseEther("1");
// before upgrade
await showGasUsage(
await gateway["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
"L2ETHGateway.withdrawETH before upgrade"
);
await showGasUsage(
await router["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
"L2GatewayRouter.withdrawETH before upgrade"
);
await showGasUsage(
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
value: amountIn,
}),
"L2ScrollMessenger.sendMessage before upgrade"
);
// do upgrade
await upgradeL2(L2_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
"L2ETHGateway.withdrawETH after upgrade"
);
await showGasUsage(
await router["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
"L2GatewayRouter.withdrawETH after upgrade"
);
await showGasUsage(
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
value: amountIn,
}),
"L2ScrollMessenger.sendMessage after upgrade"
);
});
it.skip("should succeed on L2WETHGateway", async () => {
const L1_WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const L2_WETH = "0x5300000000000000000000000000000000000004";
const L1_GATEWAY = "0x7AC440cAe8EB6328de4fA621163a792c1EA9D4fE";
const L2_GATEWAY = "0x7003E7B7186f0E6601203b99F7B8DECBfA391cf9";
const L2WETHGateway = await ethers.getContractFactory("L2WETHGateway", deployer);
const impl = await L2WETHGateway.deploy(L2_WETH, L1_WETH, L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
const gateway = await ethers.getContractAt("L2WETHGateway", L2_GATEWAY, deployer);
const amountIn = ethers.parseEther("1");
const token = await ethers.getContractAt("MockERC20", L2_WETH, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 0);
await token.approve(L2_GATEWAY, MaxUint256);
await token.approve(L2_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
"L2WETHGateway.withdrawERC20 WETH before upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 WETH before upgrade"
);
// do upgrade
await upgradeL2(L2_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
"L2WETHGateway.withdrawERC20 WETH after upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 WETH after upgrade"
);
});
it.skip("should succeed on L2StandardERC20Gateway", async () => {
const L2_USDT = "0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df";
const L1_GATEWAY = "0xD8A791fE2bE73eb6E6cF1eb0cb3F36adC9B3F8f9";
const L2_GATEWAY = "0xE2b4795039517653c5Ae8C2A9BFdd783b48f447A";
const L2StandardERC20Gateway = await ethers.getContractFactory("L2StandardERC20Gateway", deployer);
const impl = await L2StandardERC20Gateway.deploy(
L1_GATEWAY,
L2_ROUTER,
L2_MESSENGER,
"0x66e5312EDeEAef6e80759A0F789e7914Fb401484"
);
const gateway = await ethers.getContractAt("L2StandardERC20Gateway", L2_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 6);
const token = await ethers.getContractAt("MockERC20", L2_USDT, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 51);
await token.approve(L2_GATEWAY, MaxUint256);
await token.approve(L2_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
"L2StandardERC20Gateway.withdrawERC20 USDT before upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 USDT before upgrade"
);
// do upgrade
await upgradeL2(L2_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
"L2StandardERC20Gateway.withdrawERC20 USDT after upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 USDT after upgrade"
);
});
it.skip("should succeed on L2CustomERC20Gateway", async () => {
const L2_DAI = "0xcA77eB3fEFe3725Dc33bccB54eDEFc3D9f764f97";
const L1_GATEWAY = "0x67260A8B73C5B77B55c1805218A42A7A6F98F515";
const L2_GATEWAY = "0xaC78dff3A87b5b534e366A93E785a0ce8fA6Cc62";
const L2CustomERC20Gateway = await ethers.getContractFactory("L2CustomERC20Gateway", deployer);
const impl = await L2CustomERC20Gateway.deploy(L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
const gateway = await ethers.getContractAt("L2CustomERC20Gateway", L2_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 18);
const token = await ethers.getContractAt("MockERC20", L2_DAI, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 51);
await token.approve(L1_GATEWAY, MaxUint256);
await token.approve(L1_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
"L2CustomERC20Gateway.withdrawERC20 DAI before upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 DAI before upgrade"
);
// do upgrade
await upgradeL2(L2_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
"L2CustomERC20Gateway.withdrawERC20 DAI after upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 DAI after upgrade"
);
});
it.skip("should succeed on L2USDCGateway", async () => {
const L1_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const L2_USDC = "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4";
const L1_GATEWAY = "0xf1AF3b23DE0A5Ca3CAb7261cb0061C0D779A5c7B";
const L2_GATEWAY = "0x33B60d5Dd260d453cAC3782b0bDC01ce84672142";
const L2USDCGateway = await ethers.getContractFactory("L2USDCGateway", deployer);
const impl = await L2USDCGateway.deploy(L1_USDC, L2_USDC, L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
const gateway = await ethers.getContractAt("L2USDCGateway", L2_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 6);
const token = await ethers.getContractAt("MockERC20", L2_USDC, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 9);
await token.approve(L2_GATEWAY, MaxUint256);
await token.approve(L2_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
"L2USDCGateway.withdrawERC20 USDC before upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 USDC before upgrade"
);
// do upgrade
await upgradeL2(L2_GATEWAY, await impl.getAddress());
// after upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
"L2USDCGateway.withdrawERC20 USDC after upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 USDC after upgrade"
);
});
it.skip("should succeed on L2LidoGateway", async () => {
const L1_WSTETH = "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0";
const L2_WSTETH = "0xf610A9dfB7C89644979b4A0f27063E9e7d7Cda32";
const L1_GATEWAY = "0x6625C6332c9F91F2D27c304E729B86db87A3f504";
const L2_GATEWAY = "0x8aE8f22226B9d789A36AC81474e633f8bE2856c9";
const L2LidoGateway = await ethers.getContractFactory("L2LidoGateway", deployer);
const impl = await L2LidoGateway.deploy(L1_WSTETH, L2_WSTETH, L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
const gateway = await ethers.getContractAt("L2LidoGateway", L2_GATEWAY, deployer);
const amountIn = ethers.parseUnits("1", 6);
const token = await ethers.getContractAt("MockERC20", L2_WSTETH, deployer);
await mockERC20Balance(await token.getAddress(), amountIn * 10n, 51);
await token.approve(L2_GATEWAY, MaxUint256);
await token.approve(L2_ROUTER, MaxUint256);
// before upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_WSTETH, amountIn, 1e6),
"L2LidoGateway.withdrawERC20 wstETH before upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_WSTETH, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 wstETH before upgrade"
);
// do upgrade
await upgradeL2(L2_GATEWAY, await impl.getAddress());
await gateway.initializeV2(deployer.address, deployer.address, deployer.address, deployer.address);
// after upgrade
await showGasUsage(
await gateway["withdrawERC20(address,uint256,uint256)"](L2_WSTETH, amountIn, 1e6),
"L2LidoGateway.withdrawERC20 wstETH after upgrade"
);
await showGasUsage(
await router["withdrawERC20(address,uint256,uint256)"](L2_WSTETH, amountIn, 1e6),
"L2GatewayRouter.withdrawERC20 wstETH after upgrade"
);
});
});
});

View File

@@ -1,329 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { MaxUint256, Signature, ZeroAddress, ZeroHash, toBigInt } from "ethers";
import { ethers } from "hardhat";
import { GasSwap, ERC2771Forwarder, MockERC20, MockGasSwapTarget } from "../typechain";
describe("GasSwap.spec", async () => {
let deployer: HardhatEthersSigner;
let signer: HardhatEthersSigner;
let forwarder: ERC2771Forwarder;
let swap: GasSwap;
let target: MockGasSwapTarget;
let token: MockERC20;
beforeEach(async () => {
[deployer, signer] = await ethers.getSigners();
const ERC2771Forwarder = await ethers.getContractFactory("ERC2771Forwarder", deployer);
forwarder = await ERC2771Forwarder.deploy("ERC2771Forwarder");
const GasSwap = await ethers.getContractFactory("GasSwap", deployer);
swap = await GasSwap.deploy(forwarder.getAddress());
const MockGasSwapTarget = await ethers.getContractFactory("MockGasSwapTarget", deployer);
target = await MockGasSwapTarget.deploy();
const MockERC20 = await ethers.getContractFactory("MockERC20", deployer);
token = await MockERC20.deploy("x", "y", 18);
});
context("auth", async () => {
it("should initialize correctly", async () => {
expect(await swap.owner()).to.eq(deployer.address);
});
context("#updateFeeRatio", async () => {
it("should revert, when non-owner call", async () => {
await expect(swap.connect(signer).updateFeeRatio(1)).to.revertedWith("Ownable: caller is not the owner");
});
it("should succeed", async () => {
expect(await swap.feeRatio()).to.eq(ZeroAddress);
await expect(swap.updateFeeRatio(100)).to.emit(swap, "UpdateFeeRatio").withArgs(100);
expect(await swap.feeRatio()).to.eq(100);
});
});
context("#updateApprovedTarget", async () => {
it("should revert, when non-owner call", async () => {
await expect(swap.connect(signer).updateApprovedTarget(target.getAddress(), false)).to.revertedWith(
"Ownable: caller is not the owner"
);
});
it("should succeed", async () => {
expect(await swap.approvedTargets(target.getAddress())).to.eq(false);
await expect(swap.updateApprovedTarget(target.getAddress(), true))
.to.emit(swap, "UpdateApprovedTarget")
.withArgs(await target.getAddress(), true);
expect(await swap.approvedTargets(target.getAddress())).to.eq(true);
await expect(swap.updateApprovedTarget(target.getAddress(), false))
.to.emit(swap, "UpdateApprovedTarget")
.withArgs(await target.getAddress(), false);
expect(await swap.approvedTargets(target.getAddress())).to.eq(false);
});
});
context("#withdraw", async () => {
it("should revert, when non-owner call", async () => {
await expect(swap.connect(signer).withdraw(ZeroAddress, 0)).to.revertedWith("Ownable: caller is not the owner");
});
it("should succeed, when withdraw ETH", async () => {
await deployer.sendTransaction({ to: swap.getAddress(), value: ethers.parseEther("1") });
const balanceBefore = await ethers.provider.getBalance(deployer.address);
const tx = await swap.withdraw(ZeroAddress, ethers.parseEther("1"));
const receipt = await tx.wait();
const balanceAfter = await ethers.provider.getBalance(deployer.address);
expect(balanceAfter - balanceBefore).to.eq(ethers.parseEther("1") - receipt!.gasUsed * receipt!.gasPrice);
});
it("should succeed, when withdraw token", async () => {
await token.mint(swap.getAddress(), ethers.parseEther("1"));
const balanceBefore = await token.balanceOf(deployer.address);
await swap.withdraw(token.getAddress(), ethers.parseEther("1"));
const balanceAfter = await token.balanceOf(deployer.address);
expect(balanceAfter - balanceBefore).to.eq(ethers.parseEther("1"));
});
});
});
const permit = async (amount: bigint) => {
const value = {
owner: signer.address,
spender: await swap.getAddress(),
value: amount,
nonce: await token.nonces(signer.address),
deadline: MaxUint256,
};
const domain = {
name: await token.name(),
version: "1",
chainId: (await ethers.provider.getNetwork()).chainId,
verifyingContract: await token.getAddress(),
};
const types = {
Permit: [
{
name: "owner",
type: "address",
},
{
name: "spender",
type: "address",
},
{
name: "value",
type: "uint256",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
type: "uint256",
},
],
};
const signature = Signature.from(await signer.signTypedData(domain, types, value));
return signature;
};
context("swap", async () => {
it("should revert, when target not approved", async () => {
await expect(
swap.swap(
{
token: token.getAddress(),
value: 0,
deadline: 0,
r: ZeroHash,
s: ZeroHash,
v: 0,
},
{
target: target.getAddress(),
data: "0x",
minOutput: 0,
}
)
).to.revertedWith("target not approved");
});
it("should revert, when insufficient output amount", async () => {
const amountIn = ethers.parseEther("1");
const amountOut = ethers.parseEther("2");
await token.mint(signer.address, amountIn);
await deployer.sendTransaction({ to: target.getAddress(), value: amountOut });
const signature = await permit(amountIn);
await target.setToken(token.getAddress());
await target.setAmountIn(amountIn);
await swap.updateApprovedTarget(target.getAddress(), true);
await expect(
swap.connect(signer).swap(
{
token: await token.getAddress(),
value: amountIn,
deadline: MaxUint256,
r: signature.r,
s: signature.s,
v: signature.v,
},
{
target: target.getAddress(),
data: "0x8119c065",
minOutput: amountOut + 1n,
}
)
).to.revertedWith("insufficient output amount");
});
for (const refundRatio of [0n, 1n, 5n]) {
for (const feeRatio of ["0", "5", "50"]) {
it(`should succeed, when swap by signer directly, with feeRatio[${feeRatio}%] refundRatio[${refundRatio}%]`, async () => {
const amountIn = ethers.parseEther("1");
const amountOut = ethers.parseEther("2");
await token.mint(signer.address, amountIn);
await deployer.sendTransaction({ to: target.getAddress(), value: amountOut });
const signature = await permit(amountIn);
await target.setToken(token.getAddress());
await target.setAmountIn(amountIn);
await target.setRefund((amountIn * refundRatio) / 100n);
await swap.updateApprovedTarget(target.getAddress(), true);
await swap.updateFeeRatio(ethers.parseEther(feeRatio) / 100n);
const fee = (amountOut * toBigInt(feeRatio)) / 100n;
const balanceBefore = await ethers.provider.getBalance(signer.address);
const tx = await swap.connect(signer).swap(
{
token: await token.getAddress(),
value: amountIn,
deadline: MaxUint256,
r: signature.r,
s: signature.s,
v: signature.v,
},
{
target: target.getAddress(),
data: "0x8119c065",
minOutput: amountOut - fee,
}
);
const receipt = await tx.wait();
const balanceAfter = await ethers.provider.getBalance(signer.address);
expect(balanceAfter - balanceBefore).to.eq(amountOut - fee - receipt!.gasUsed * receipt!.gasPrice);
expect(await token.balanceOf(signer.address)).to.eq((amountIn * refundRatio) / 100n);
});
it(`should succeed, when swap by signer with forwarder, with feeRatio[${feeRatio}%] refundRatio[${refundRatio}%]`, async () => {
const amountIn = ethers.parseEther("1");
const amountOut = ethers.parseEther("2");
await token.mint(signer.address, amountIn);
await deployer.sendTransaction({ to: await target.getAddress(), value: amountOut });
const permitSignature = await permit(amountIn);
await target.setToken(token.getAddress());
await target.setAmountIn(amountIn);
await target.setRefund((amountIn * refundRatio) / 100n);
await swap.updateApprovedTarget(target.getAddress(), true);
await swap.updateFeeRatio(ethers.parseEther(feeRatio) / 100n);
const fee = (amountOut * toBigInt(feeRatio)) / 100n;
const reqWithoutSignature = {
from: signer.address,
to: await swap.getAddress(),
value: 0n,
gas: 1000000,
nonce: await forwarder.nonces(signer.address),
deadline: 2000000000,
data: swap.interface.encodeFunctionData("swap", [
{
token: await token.getAddress(),
value: amountIn,
deadline: MaxUint256,
r: permitSignature.r,
s: permitSignature.s,
v: permitSignature.v,
},
{
target: await target.getAddress(),
data: "0x8119c065",
minOutput: amountOut - fee,
},
]),
};
const signature = await signer.signTypedData(
{
name: "ERC2771Forwarder",
version: "1",
chainId: (await ethers.provider.getNetwork()).chainId,
verifyingContract: await forwarder.getAddress(),
},
{
ForwardRequest: [
{
name: "from",
type: "address",
},
{
name: "to",
type: "address",
},
{
name: "value",
type: "uint256",
},
{
name: "gas",
type: "uint256",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
type: "uint48",
},
{
name: "data",
type: "bytes",
},
],
},
reqWithoutSignature
);
const balanceBefore = await ethers.provider.getBalance(signer.address);
await forwarder.execute({
from: reqWithoutSignature.from,
to: reqWithoutSignature.to,
value: reqWithoutSignature.value,
gas: reqWithoutSignature.gas,
deadline: reqWithoutSignature.deadline,
data: reqWithoutSignature.data,
signature,
});
const balanceAfter = await ethers.provider.getBalance(signer.address);
expect(balanceAfter - balanceBefore).to.eq(amountOut - fee);
expect(await token.balanceOf(signer.address)).to.eq((amountIn * refundRatio) / 100n);
});
}
}
});
});

View File

@@ -1,233 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { expect } from "chai";
import { BigNumberish, ZeroHash, concat, encodeRlp, toBeHex, toBigInt } from "ethers";
import { ethers } from "hardhat";
import { L1BlockContainer } from "../typechain";
interface IImportTestConfig {
hash: string;
parentHash: string;
uncleHash: string;
coinbase: string;
stateRoot: string;
transactionsRoot: string;
receiptsRoot: string;
logsBloom: string;
difficulty: BigNumberish;
blockHeight: number;
gasLimit: BigNumberish;
gasUsed: BigNumberish;
blockTimestamp: number;
extraData: string;
mixHash: string;
blockNonce: string;
baseFee: BigNumberish;
}
const testcases: Array<IImportTestConfig> = [
{
hash: "0x02250e97ef862444dd1d70acbe925c289bb2acf20a808cb8f4d1409d3adcfa1b",
parentHash: "0x95e612b2a734f5a8c6aad3f6662b18f983ce8b653854d7c307bf999d9be323af",
uncleHash: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
coinbase: "0x690b9a9e9aa1c9db991c7721a92d351db4fac990",
stateRoot: "0x8d77db2a63cee63ae6d793f839a7513dfc50194f325b96a5326d724f5dc16320",
transactionsRoot: "0xe4ce5f0e2fc5fd8a7ad55c2a31c522ded4054b89065c627d26230b45cd585fed",
receiptsRoot: "0x10b2f34da3e6a1db9498ab36bb17b063763b8eb33492ccc621491b33bcb62bdd",
logsBloom:
"0x18b80159addab073ac340045c4ef982442653840c8074a50159bd9626ae0590740d07273d0c859005b634059c8ca9bb18364573e7ebe79a40aa08225942370c3dc6c0af2ea33cba07900961de2b011aabb8024270d4626d1028a2f0dcd780c60ce933b169b02c8c329c18b000aaf08c98245d8ad949e7d61102d5516489fa924f390c3a71642d7e6044c85a20952568d60cf24c38baff04c244b10eac87a6da8bb32c1535ea2613064a246d598c02444624a8d5a1b201a4270a7868a97aa4530838c2e7a192a88e329daf0334c728b7c057f684f1d28c07d0d2c1dc63868a1088010ae0b661073142e468ae062151e00e5108400e1a99c4111153828610874bb",
difficulty: "0x0",
blockHeight: 0xf766a8,
gasLimit: "0x1c9c380",
gasUsed: "0xe6f194",
blockTimestamp: 0x639f69e3,
extraData: "0x406275696c64657230783639",
mixHash: "0xc1e37ce2b7ece4556ec87ea6d420a1a3610d49c58dfccec6998222fbf9cd64a2",
blockNonce: "0x0000000000000000",
baseFee: "0x2b96fa5cc",
},
{
hash: "0x2da4bf7cef55d6207af2095db5543df16acbd95dc66eef02d9764277c5b0895d",
parentHash: "0xde18012932b21820fbb48ef85b46774873383e75b062bc0c6a4761fbe87bad13",
uncleHash: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
coinbase: "0x690b9a9e9aa1c9db991c7721a92d351db4fac990",
stateRoot: "0x1f101f54c3df5630c9d45224c95d71a57479992e174cdbda0c4ada30e657a465",
transactionsRoot: "0xc2b29438a5f55998879356cbc8006a90d2ba88a9841b3894c8da5840dd797f19",
receiptsRoot: "0xbd3608b6af5464b446db44fd289a980f417447b31ff15dd6d48c72fc8f4fef8d",
logsBloom:
"0xd9e5f4f1e559388eb8193295ab2d3aab30c588d31e381c4060715d0a7ce607360b15d7a0d88e406c60135e0abcecd1d816c11f8cbbb2a80a9b4a00375d6cf356cb78f2934261ab09ea03df29dab5dbe4aefea506f7fd0eaa1a8b1fc8db5079613a49d80ca7e7997a20c7158399022c1dc9853f5b401b86587249fc96ca6fbc2dab1fdeb203ca258c94dd0bc821b38f9f60128591f3cd224c5c207b76b754e537bef8ebe731effae356235dd71bd7b5494bead124a8b5bb0ba02e46721d3ec3c20608880b1d35a17f6a1027d20c7b902e5d7b2ec8177b1aff9dcfbb4729d1e3201e78fa1b3c30e66a590cb5a7cac7afe0b0b1a6c94d5e39c9a20908358b805c81",
difficulty: "0x0",
blockHeight: 0xf766d8,
gasLimit: "0x1c9c380",
gasUsed: "0xf8adad",
blockTimestamp: 0x639f6c23,
extraData: "0x6275696c64657230783639",
mixHash: "0x6066061b78b385483d960faa29ee40e79ea67769f5e697ecb70a0fce677804af",
blockNonce: "0x0000000000000000",
baseFee: "0x2aca8b608",
},
{
hash: "0x4ddeee3e8d62e961080711e48d8083f164789e78cc90e4362c133063b566d64a",
parentHash: "0x9d190c6d49352d628e321853967dd499d78c521daad73652ed1978db5652f58a",
uncleHash: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
coinbase: "0xcd458d7f11023556cc9058f729831a038cb8df9c",
stateRoot: "0x3620665f9d094aac16e0762b733e814f4e09177a232f85d406271b60e4f2b58f",
transactionsRoot: "0x200f5acb65631c48c32c94ae95afe095134132939a01422da5c7c6d0e7f62cb3",
receiptsRoot: "0xc140420782bc76ff326d18b13427c991e9434a554b9ae82bbf09cca7b6ae4036",
logsBloom:
"0x00a8cd20c1402037d2a51100c0895279410502288134d22313912bb7b42e504f850f417d9000000a41949b284b40210406019c0e28122d462c05c11120ac2c680800c0348066a23e7a9e042a9d20e4e0041114830d443160a46b5e02ec300d41330cf0652602140e1580b4c82d1228c000005be72c900f7152093d93ca4880062185952cacc6c8d1405a0c5823bb4284a04a44c92b41462c2420a870685438809a99850acc936c408c24e882a01517086a20a067a2e4e01a20e106078828706c7c00a0234e6830c80b911900291a134475208a4335ab0018a9048d4628186043303b722a79645a104c0e12a506404f45c428660a105d105010482852540b9a6b",
difficulty: "0x2ae28b0d3154b6",
blockHeight: 0xecb6fc,
gasLimit: "0x1c9c30d",
gasUsed: "0xb93955",
blockTimestamp: 0x631d8207,
extraData: "0x706f6f6c696e2e636f6d2050cabdd319bf3175",
mixHash: "0x18d61005875e902e1bbba1045fd6701df170230c0ffb37f2e77fbc2051b987cf",
blockNonce: "0xe8775f73466671e3",
baseFee: "0x18c9de157",
},
];
function encodeHeader(test: IImportTestConfig): string {
return encodeRlp([
test.parentHash,
test.uncleHash,
test.coinbase,
test.stateRoot,
test.transactionsRoot,
test.receiptsRoot,
test.logsBloom,
toBigInt(test.difficulty) === 0n ? "0x" : toBeHex(test.difficulty),
toBeHex(test.blockHeight),
toBeHex(test.gasLimit),
toBeHex(test.gasUsed),
toBeHex(test.blockTimestamp),
test.extraData,
test.mixHash,
test.blockNonce,
toBeHex(test.baseFee),
]);
}
describe("L1BlockContainer", async () => {
let container: L1BlockContainer;
for (const test of testcases) {
context(`import block[${test.hash}] height[${test.blockHeight}]`, async () => {
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const L1BlockContainer = await ethers.getContractFactory("L1BlockContainer", deployer);
container = await L1BlockContainer.deploy(deployer.address);
const Whitelist = await ethers.getContractFactory("Whitelist", deployer);
const whitelist = await Whitelist.deploy(deployer.address);
await whitelist.updateWhitelistStatus([deployer.address], true);
await container.updateWhitelist(whitelist.getAddress());
});
it("should revert, when sender not allowed", async () => {
const [, signer] = await ethers.getSigners();
await container.initialize(
test.parentHash,
test.blockHeight - 1,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
await expect(container.connect(signer).importBlockHeader(ZeroHash, "0x", false)).to.revertedWith(
"Not whitelisted sender"
);
});
it("should revert, when block hash mismatch", async () => {
await container.initialize(
test.parentHash,
test.blockHeight - 1,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
const headerRLP = encodeHeader(test);
await expect(container.importBlockHeader(test.parentHash, headerRLP, false)).to.revertedWith(
"Block hash mismatch"
);
});
it("should revert, when has extra bytes", async () => {
await container.initialize(
test.parentHash,
test.blockHeight - 1,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
const headerRLP = encodeHeader(test);
await expect(container.importBlockHeader(test.hash, concat([headerRLP, "0x00"]), false)).to.revertedWith(
"Header RLP length mismatch"
);
});
it("should revert, when parent not imported", async () => {
await container.initialize(
ZeroHash,
test.blockHeight - 1,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
const headerRLP = encodeHeader(test);
await expect(container.importBlockHeader(test.hash, headerRLP, false)).to.revertedWith("Parent not imported");
});
it("should revert, when block height mismatch", async () => {
await container.initialize(
test.parentHash,
test.blockHeight,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
const headerRLP = encodeHeader(test);
await expect(container.importBlockHeader(test.hash, headerRLP, false)).to.revertedWith("Block height mismatch");
});
it("should revert, when parent block has larger timestamp", async () => {
await container.initialize(
test.parentHash,
test.blockHeight - 1,
test.blockTimestamp + 1,
test.baseFee,
test.stateRoot
);
const headerRLP = encodeHeader(test);
await expect(container.importBlockHeader(test.hash, headerRLP, false)).to.revertedWith(
"Parent block has larger timestamp"
);
});
it(`should succeed`, async () => {
await container.initialize(
test.parentHash,
test.blockHeight - 1,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
expect(await container.latestBlockHash()).to.eq(test.parentHash);
const headerRLP = encodeHeader(test);
await expect(container.importBlockHeader(test.hash, headerRLP, false))
.to.emit(container, "ImportBlock")
.withArgs(test.hash, test.blockHeight, test.blockTimestamp, test.baseFee, test.stateRoot);
expect(await container.getStateRoot(test.hash)).to.eq(test.stateRoot);
expect(await container.getBlockTimestamp(test.hash)).to.eq(test.blockTimestamp);
expect(await container.latestBlockHash()).to.eq(test.hash);
expect(await container.latestBaseFee()).to.eq(test.baseFee);
expect(await container.latestBlockNumber()).to.eq(test.blockHeight);
expect(await container.latestBlockTimestamp()).to.eq(test.blockTimestamp);
});
});
}
});

View File

@@ -1,393 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { L1MessageQueue, L2GasPriceOracle } from "../typechain";
import {
MaxUint256,
ZeroAddress,
concat,
encodeRlp,
getAddress,
hexlify,
keccak256,
randomBytes,
toBeHex,
toBigInt,
} from "ethers";
describe("L1MessageQueue", async () => {
let deployer: HardhatEthersSigner;
let scrollChain: HardhatEthersSigner;
let messenger: HardhatEthersSigner;
let gateway: HardhatEthersSigner;
let signer: HardhatEthersSigner;
let oracle: L2GasPriceOracle;
let queue: L1MessageQueue;
const deployProxy = async (name: string, admin: string, args: any[]): Promise<string> => {
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const Factory = await ethers.getContractFactory(name, deployer);
const impl = args.length > 0 ? await Factory.deploy(...args) : await Factory.deploy();
const proxy = await TransparentUpgradeableProxy.deploy(impl.getAddress(), admin, "0x");
return proxy.getAddress();
};
beforeEach(async () => {
[deployer, scrollChain, messenger, gateway, signer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
const admin = await ProxyAdmin.deploy();
queue = await ethers.getContractAt(
"L1MessageQueue",
await deployProxy("L1MessageQueue", await admin.getAddress(), [
messenger.address,
scrollChain.address,
gateway.address,
]),
deployer
);
oracle = await ethers.getContractAt(
"L2GasPriceOracle",
await deployProxy("L2GasPriceOracle", await admin.getAddress(), []),
deployer
);
await oracle.initialize(21000, 50000, 8, 16);
await queue.initialize(messenger.address, scrollChain.address, ZeroAddress, oracle.getAddress(), 10000000);
});
context("auth", async () => {
it("should initialize correctly", async () => {
expect(await queue.owner()).to.eq(deployer.address);
expect(await queue.messenger()).to.eq(messenger.address);
expect(await queue.scrollChain()).to.eq(scrollChain.address);
expect(await queue.enforcedTxGateway()).to.eq(gateway.address);
expect(await queue.gasOracle()).to.eq(await oracle.getAddress());
expect(await queue.maxGasLimit()).to.eq(10000000);
});
it("should revert, when initialize again", async () => {
await expect(queue.initialize(ZeroAddress, ZeroAddress, ZeroAddress, ZeroAddress, 0)).to.revertedWith(
"Initializable: contract is already initialized"
);
});
context("#updateGasOracle", async () => {
it("should revert, when non-owner call", async () => {
await expect(queue.connect(signer).updateGasOracle(ZeroAddress)).to.revertedWith(
"Ownable: caller is not the owner"
);
});
it("should succeed", async () => {
expect(await queue.gasOracle()).to.eq(await oracle.getAddress());
await expect(queue.updateGasOracle(deployer.address))
.to.emit(queue, "UpdateGasOracle")
.withArgs(await oracle.getAddress(), deployer.address);
expect(await queue.gasOracle()).to.eq(deployer.address);
});
});
context("#updateMaxGasLimit", async () => {
it("should revert, when non-owner call", async () => {
await expect(queue.connect(signer).updateMaxGasLimit(0)).to.revertedWith("Ownable: caller is not the owner");
});
it("should succeed", async () => {
expect(await queue.maxGasLimit()).to.eq(10000000);
await expect(queue.updateMaxGasLimit(0)).to.emit(queue, "UpdateMaxGasLimit").withArgs(10000000, 0);
expect(await queue.maxGasLimit()).to.eq(0);
});
});
});
context("#computeTransactionHash", async () => {
it("should succeed", async () => {
const sender = "0xb2a70fab1a45b1b9be443b6567849a1702bc1232";
const target = "0xcb18150e4efefb6786130e289a5f61a82a5b86d7";
const transactionType = "0x7E";
for (const nonce of [0n, 1n, 127n, 128n, 22334455n, MaxUint256]) {
for (const value of [0n, 1n, 127n, 128n, 22334455n, MaxUint256]) {
for (const gasLimit of [0n, 1n, 127n, 128n, 22334455n, MaxUint256]) {
for (const dataLen of [0, 1, 2, 3, 4, 55, 56, 100]) {
const tests = [randomBytes(dataLen)];
if (dataLen === 1) {
for (const byte of [0, 1, 127, 128]) {
tests.push(Uint8Array.from([byte]));
}
}
for (const data of tests) {
const transactionPayload = encodeRlp([
nonce === 0n ? "0x" : toBeHex(nonce),
gasLimit === 0n ? "0x" : toBeHex(gasLimit),
target,
value === 0n ? "0x" : toBeHex(value),
data,
sender,
]);
const payload = concat([transactionType, transactionPayload]);
const expectedHash = keccak256(payload);
const computedHash = await queue.computeTransactionHash(sender, nonce, value, target, gasLimit, data);
if (computedHash !== expectedHash) {
console.log(hexlify(transactionPayload));
console.log(nonce, gasLimit, target, value, data, sender);
}
expect(expectedHash).to.eq(computedHash);
}
}
}
}
}
});
});
context("#appendCrossDomainMessage", async () => {
it("should revert, when non-messenger call", async () => {
await expect(queue.connect(signer).appendCrossDomainMessage(ZeroAddress, 0, "0x")).to.revertedWith(
"Only callable by the L1ScrollMessenger"
);
});
it("should revert, when exceed maxGasLimit", async () => {
await expect(queue.connect(messenger).appendCrossDomainMessage(ZeroAddress, 10000001, "0x")).to.revertedWith(
"Gas limit must not exceed maxGasLimit"
);
});
it("should revert, when below intrinsic gas", async () => {
await expect(queue.connect(messenger).appendCrossDomainMessage(ZeroAddress, 0, "0x")).to.revertedWith(
"Insufficient gas limit, must be above intrinsic gas"
);
});
it("should succeed", async () => {
expect(await queue.nextCrossDomainMessageIndex()).to.eq(0n);
const sender = getAddress(
toBeHex((toBigInt(messenger.address) + toBigInt("0x1111000000000000000000000000000000001111")) % 2n ** 160n)
.slice(2)
.padStart(40, "0")
);
const hash = await queue.computeTransactionHash(sender, 0, 0, signer.address, 100000, "0x01");
await expect(queue.connect(messenger).appendCrossDomainMessage(signer.address, 100000, "0x01"))
.to.emit(queue, "QueueTransaction")
.withArgs(sender, signer.address, 0, 0, 100000, "0x01");
expect(await queue.nextCrossDomainMessageIndex()).to.eq(1n);
expect(await queue.getCrossDomainMessage(0)).to.eq(hash);
});
});
context("#appendEnforcedTransaction", async () => {
it("should revert, when non-gateway call", async () => {
await expect(
queue.connect(signer).appendEnforcedTransaction(signer.address, ZeroAddress, 0, 0, "0x")
).to.revertedWith("Only callable by the EnforcedTxGateway");
});
it("should revert, when sender is not EOA", async () => {
await expect(
queue.connect(gateway).appendEnforcedTransaction(queue.getAddress(), ZeroAddress, 0, 0, "0x")
).to.revertedWith("only EOA");
});
it("should revert, when exceed maxGasLimit", async () => {
await expect(
queue.connect(gateway).appendEnforcedTransaction(signer.address, ZeroAddress, 0, 10000001, "0x")
).to.revertedWith("Gas limit must not exceed maxGasLimit");
});
it("should revert, when below intrinsic gas", async () => {
await expect(
queue.connect(gateway).appendEnforcedTransaction(signer.address, ZeroAddress, 0, 0, "0x")
).to.revertedWith("Insufficient gas limit, must be above intrinsic gas");
});
it("should succeed", async () => {
expect(await queue.nextCrossDomainMessageIndex()).to.eq(0n);
const sender = signer.address;
const hash = await queue.computeTransactionHash(sender, 0, 200, signer.address, 100000, "0x01");
await expect(
queue.connect(gateway).appendEnforcedTransaction(signer.address, signer.address, 200, 100000, "0x01")
)
.to.emit(queue, "QueueTransaction")
.withArgs(sender, signer.address, 200, 0, 100000, "0x01");
expect(await queue.nextCrossDomainMessageIndex()).to.eq(1n);
expect(await queue.getCrossDomainMessage(0)).to.eq(hash);
});
});
context("#popCrossDomainMessage", async () => {
it("should revert, when non-scrollChain call", async () => {
await expect(queue.connect(signer).popCrossDomainMessage(0, 0, 0)).to.revertedWith(
"Only callable by the ScrollChain"
);
});
it("should revert, when pop too many messages", async () => {
await expect(queue.connect(scrollChain).popCrossDomainMessage(0, 257, 0)).to.revertedWith(
"pop too many messages"
);
});
it("should revert, when start index mismatch", async () => {
await expect(queue.connect(scrollChain).popCrossDomainMessage(1, 256, 0)).to.revertedWith("start index mismatch");
});
it("should succeed", async () => {
// append 512 messages
for (let i = 0; i < 256 * 2; i++) {
await queue.connect(messenger).appendCrossDomainMessage(ZeroAddress, 1000000, "0x");
}
// pop 50 messages with no skip
await expect(queue.connect(scrollChain).popCrossDomainMessage(0, 50, 0))
.to.emit(queue, "DequeueTransaction")
.withArgs(0, 50, 0);
for (let i = 0; i < 50; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(false);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
expect(await queue.pendingQueueIndex()).to.eq(50);
// pop 10 messages all skip
await expect(queue.connect(scrollChain).popCrossDomainMessage(50, 10, 1023))
.to.emit(queue, "DequeueTransaction")
.withArgs(50, 10, 1023);
expect(await queue.pendingQueueIndex()).to.eq(60);
for (let i = 50; i < 60; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(true);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
// pop 20 messages, skip first 5
await expect(queue.connect(scrollChain).popCrossDomainMessage(60, 20, 31))
.to.emit(queue, "DequeueTransaction")
.withArgs(60, 20, 31);
expect(await queue.pendingQueueIndex()).to.eq(80);
for (let i = 60; i < 65; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(true);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
for (let i = 65; i < 80; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(false);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
// pop 256 messages with random skip
const bitmap = toBigInt("0x496525059c3f33758d17030403e45afe067b8a0ae1317cda0487fd2932cbea1a");
const tx = await queue.connect(scrollChain).popCrossDomainMessage(80, 256, bitmap);
await expect(tx).to.emit(queue, "DequeueTransaction").withArgs(80, 256, bitmap);
console.log("gas used:", (await tx.wait())!.gasUsed.toString());
for (let i = 80; i < 80 + 256; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(((bitmap >> toBigInt(i - 80)) & 1n) === 1n);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
});
// @note skip this random benchmark tests
for (const count1 of [1, 2, 128, 129, 256]) {
for (const count2 of [1, 2, 128, 129, 256]) {
for (const count3 of [1, 2, 128, 129, 256]) {
it.skip(`should succeed on random tests, pop three times each with ${count1} ${count2} ${count3} msgs`, async () => {
// append count1 + count2 + count3 messages
for (let i = 0; i < count1 + count2 + count3; i++) {
await queue.connect(messenger).appendCrossDomainMessage(ZeroAddress, 1000000, "0x");
}
// first pop `count1` messages
const bitmap1 = toBigInt(randomBytes(32));
let tx = await queue.connect(scrollChain).popCrossDomainMessage(0, count1, bitmap1);
await expect(tx)
.to.emit(queue, "DequeueTransaction")
.withArgs(0, count1, bitmap1 & ((1n << toBigInt(count1)) - 1n));
for (let i = 0; i < count1; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(((bitmap1 >> toBigInt(i)) & 1n) === 1n);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
// then pop `count2` messages
const bitmap2 = toBigInt(randomBytes(32));
tx = await queue.connect(scrollChain).popCrossDomainMessage(count1, count2, bitmap2);
await expect(tx)
.to.emit(queue, "DequeueTransaction")
.withArgs(count1, count2, bitmap2 & ((1n << toBigInt(count2)) - 1n));
for (let i = 0; i < count2; i++) {
expect(await queue.isMessageSkipped(i + count1)).to.eq(((bitmap2 >> toBigInt(i)) & 1n) === 1n);
expect(await queue.isMessageDropped(i + count1)).to.eq(false);
}
// last pop `count3` messages
const bitmap3 = toBigInt(randomBytes(32));
tx = await queue.connect(scrollChain).popCrossDomainMessage(count1 + count2, count3, bitmap3);
await expect(tx)
.to.emit(queue, "DequeueTransaction")
.withArgs(count1 + count2, count3, bitmap3 & ((1n << toBigInt(count3)) - 1n));
for (let i = 0; i < count3; i++) {
expect(await queue.isMessageSkipped(i + count1 + count2)).to.eq(((bitmap3 >> toBigInt(i)) & 1n) === 1n);
expect(await queue.isMessageDropped(i + count1 + count2)).to.eq(false);
}
});
}
}
}
});
context("#dropCrossDomainMessage", async () => {
it("should revert, when non-messenger call", async () => {
await expect(queue.connect(signer).dropCrossDomainMessage(0)).to.revertedWith(
"Only callable by the L1ScrollMessenger"
);
});
it("should revert, when drop non-skipped message", async () => {
// append 10 messages
for (let i = 0; i < 10; i++) {
await queue.connect(messenger).appendCrossDomainMessage(ZeroAddress, 1000000, "0x");
}
// pop 5 messages with no skip
await expect(queue.connect(scrollChain).popCrossDomainMessage(0, 5, 0))
.to.emit(queue, "DequeueTransaction")
.withArgs(0, 5, 0);
for (let i = 0; i < 5; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(false);
expect(await queue.isMessageDropped(i)).to.eq(false);
}
expect(await queue.pendingQueueIndex()).to.eq(5);
for (let i = 0; i < 5; i++) {
await expect(queue.connect(messenger).dropCrossDomainMessage(i)).to.revertedWith("drop non-skipped message");
}
// drop pending message
for (let i = 6; i < 10; i++) {
await expect(queue.connect(messenger).dropCrossDomainMessage(i)).to.revertedWith("cannot drop pending message");
}
});
it("should succeed", async () => {
// append 10 messages
for (let i = 0; i < 10; i++) {
await queue.connect(messenger).appendCrossDomainMessage(ZeroAddress, 1000000, "0x");
}
// pop 10 messages, all skipped
await expect(queue.connect(scrollChain).popCrossDomainMessage(0, 10, 0x3ff))
.to.emit(queue, "DequeueTransaction")
.withArgs(0, 10, 0x3ff);
for (let i = 0; i < 10; i++) {
expect(await queue.isMessageSkipped(i)).to.eq(true);
expect(await queue.isMessageDropped(i)).to.eq(false);
await expect(queue.connect(messenger).dropCrossDomainMessage(i)).to.emit(queue, "DropTransaction").withArgs(i);
await expect(queue.connect(messenger).dropCrossDomainMessage(i)).to.revertedWith("message already dropped");
expect(await queue.isMessageSkipped(i)).to.eq(true);
expect(await queue.isMessageDropped(i)).to.eq(true);
}
});
});
});

View File

@@ -1,143 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { expect } from "chai";
import { concat } from "ethers";
import { ethers } from "hardhat";
import { MockPatriciaMerkleTrieVerifier } from "../typechain";
interface ITestConfig {
block: number;
account: string;
storage: string;
expectedRoot: string;
expectedValue: string;
accountProof: string[];
storageProof: string[];
}
const testcases: Array<ITestConfig> = [
{
block: 16212738,
account: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
storage: "0xb17c5049c06186507ed9d55e735dc0342e08579866e7ed881de010624b3896dd",
expectedRoot: "0x5dd9637058e605949321a683ab1e6c56ae6041a05cdf97355696f93309799391",
expectedValue: "0x00000000000000000000000000000000000000000000000052ab3594ab17a60b",
accountProof: [
"0xf90211a04cfe239817b200a743356abfc6e5b08d9951e90f3932f57a7c12014d9968b040a02c94e10276ccd6a461e94da963f126e396d12f50a3389966705dbb0ece7f67aca0f28acd17ade90c99e92e3e155a46076ef89f51f22caf45ec8f5affc240073cf6a0f26e26128daf3ecbb7a37eb10afad22741725a1ce43819f1f573da6f1e6fc2c9a020e3325c4125cde3a948d7a68530a8f8979591c17f445bf96b4716d64833f6c8a0def41ac472c300aed57feb95cf7426fcca53d4c0007afabfb0d6c4d3b4ad95fea0a65435daeb1a371b29c3037a01230d19872e2bdb1a97aeafe610df01dd9937c3a0c4d93f1c9037597d4b07388551773f9578203a8abf4f3bfabd6eaf58070f32d5a0d008f86640c7313e00f897b2b9416da54ea2182fa98785e583367e42035fc0baa072981aa04d506601aeb2cf8689ff23dff82a52a29e1d401dfe96baa2550b977ea065a9e75f35c97436334ad2498ea3fe4296829ad7b005e65af34fd10ddb368631a0b326e41a44cadb3e78fd84571f5e0f9da6b5ee5dfcfb1c88a6b1fcdb13fe6beca0e32897d4de5966ed95729c2a68354d1ef7f27a9b8a5cdaec592965bcc5b339d3a0022b816b5afca265766e67427b45682ade004a780e7e3667b41930a1d087230ea0dc0eb205c8cc3642fe2f03252b238891819a8528f30fc0207c2271290e8de9a1a0554966428442b6b9188a4b4945aa550f32615e4b1b1d3776b07c9d18ba0146af80",
"0xf90211a00ee4696104bbdba0094ca30daa4eae871b1dc0c2ccb07d8f24c7c89193904607a080893f1dc4ded5ddfa49eb36a618a0c3525c58890ae7e4be006e6988980cd15ca04ad58fd70d3cabb3d59144f729105997d3f07c0223a41dbc9b1507d1aa7825cba03bbe2d774e64d6577f1e90ef42b20664b4707649b00e957e369e97a1f03dc762a0107ec21d49839dbbb267fe5ca58c615af81df1752b7f49c8ce2da952a132cebba0d4bd3d22a406960040f86aa8fff6c9e29a2337560145730f9e3612844d67dd1ea09b1edb047a63e19ba02f894a19bfe2d4fcb9052e0dddd6d40dfa52351b3e973ea0a397a48dcdbeef118776a2cbd06fa400d1bedc99ed9f61d4f4513cc6aa7c29daa031f5b24b9027eef2c12015db45ef79c6f57681a6818173e00ddb1050567be4aea035748b7d80884cd8ee2d53523e9aa49186091b28dadd09e1a4f94b8ba3e3c995a055f851741c59287e048a908539c348c6555c098ac16fa074395d530b67f076b9a0f189025cd5b04a3b73bcdbdfa0d9637a0ff389f7b9a481efc2cb984484cb106ea0d7e874ea3b71239bbdb6f01287f58508816b270a218293987e42618f6b982777a0447c72ec8a23e35ba10b61462c11c654653556682994de6ea7866a538320fd3ea0d52ef935a9abaa771614224e75c9d06b8d94270a5ab11b95635f3d646bc7f80fa020d93fff55bcd20b764b2a4261b448cac23fa19dd64dbb7d33345a27b1c02dce80",
"0xf90211a0aa579a2bef0815ecbe72dcc7a478494f4ddf6e6a821fed8b8e5e22f96be95fb1a0f7be1171a1b188f0159315731796369ea543043b3f2076ad688f2bda5315d4f6a0ac7901c3cece0eafdb607bf3f6981aac2741804c77b0db674d7bc69c6e0841d5a0c1bf87d0fc7ff63bc43bb453920d13b00ed2e126931fe431206519e47f2aff58a0fbb3f885d4e17a30daad80568b76ca24b70f95ddb3840598c9cbf5499caa13d2a009566520886f90ae776076398c3393585110ea164c8a1e6c47980ec67fbbbf9ea0709eec3f022710443237d2ee3d967abb9fe295b335dbc783768cc2396ba0b28ea02003180468280c9bf5819207be30c9f3176a0cd68a57b43fe353565a5d42b62aa09817a0745b614df9aa5268081c06eaa5d6c057c86e0253ee26f081b9fc5487a1a073265752f6c91428565dab106305f47b8c609522ee518b4f391c7f8951f5394fa03ef7529bb0ee4030c994910ba8d8cd0eafbfcc4d7f7a0fe9b528b09360ab12e0a093330c4eb263124f35f26572747b59957744f1c39cb91e413b599d27e07dcaf6a022dec6cd45c7db6901c364be4226d54fd74552af51d835d605d1efde50a374c0a0007c30f8707814de913a9edd9bf09fe614676b2ed5497ea06bd157e5ec1718c2a0e6d9335dee9c32e74ae736ddccb15bbbe3ca07c347e7d038a6103877d1cefd31a02d5576458404a2e48f2263741a2c5ff181ff03939e1952cd616412c98edacdae80",
"0xf90211a0f10b8f4ec168083a8021ac8201365f45d63ad461fdf4cf8c50342499f197f5f3a02341a492492fa8323462dad1af3ab7094b76ae3666c4d081ec8d24c9e0da451da0017ce2794246eda28f5b1b3fee05dd269dabb29f71799ca7c3dca67764132c82a02b629e4b9b699796651ad13840a0d06721041de42d09f22ddf3e0f7c89ade82aa076d2c3f907c842c8e76454503b7ef1c9f52e93fc3830b4b8cd63dadeefa8fd4da09284abd6431d107e527627dd78d3cc2a655f7e364470ef620fb7fada3fcece73a00afefb47543ea7c9866f274ab4aa14ee261ffcd0c8b7c8c4e66f1ff02eda6ed3a02045ebe244660a6cae3467637f3e0b27c003cefe72681c47acb2e9766c1f17c7a08fc1ee83563261f1104687cefe451fedcff6caf2dae3f3a2a382b1a0bad7109ba00afa5fe38079cb86511e0842b62af452a78ecd43dc6c54351ed3ec923769088ca0a9c36efeb72874a37dd282f309ff318b6e9464ece30c63ba80bfbc5e5f76f163a030b918045e6233a81833658889f54cedef0f1052aa56e673649a955bc8fee94aa0eae7097667819b85f90f7d4a72d9a8147dccf5fbd744050a743f029e0a79c725a0671e20fc1d94cdb487e0a8cb8c752fd3b4c2f759b9a905134f7a880e1dcdc96da0425857c455a0e10c7cae230d3b3a3309ff5732b55ca2186cc9ddaecff5460490a0b10db994f51f52b29f43281c561f2c62f2be921c5f585fb441760ce9aa4d3d1a80",
"0xf90211a0fd942eae2655a391e59dc2779f53209542fcc140b96e4b93cff3d8cb417e6efba0bd3535c9bfa5a7b939c7dff9307610a5958f8a785d2dcf7eeaf84624d0e457cca05ce0a4917922d7b302fca1badd446897f360b11d60be9802c45136166a81dc79a0731d140390c684a63ecf3ba9d392c73b8fb1bf2864d4b90eff813e953f66ac4aa010bb21166ea999880a179d6669704ecf6c50ea9e47eb674d9b077a7d4c4f9baba085dab7106099e19e2c978e8e814a7749af5bbdbe1131333713e612898a8d62c1a012720a68371573fe69f384950b871b09a44af5fe2c4870f231a58e07190c1b36a089e816024bd04ad03ca66e47323feaf5d975b3ec41b46fb124ba9a9299c26da7a0827ecf55875811b3b25696b3737ead4817641d29ed46d5c4892d098357b699e2a06450a823c9feb0adcd77aec2d3156057f2c93f83670da26afed344e2c6a8f5a7a045fd2f25ecd36a65186513e409fa3b3e3f3a0f7f60f5951c76d2ce10235db1bfa06819009da16eeacf224ce65fc7dc8052cc2f4dd32813441801ac3be9e9db98c5a0ae81fa6db4342f607a35aea6a10047c1848c9251d87140efd6c24685ab964b08a0ee867ebe92374b199244599920a3a0fd13ca24030ae6c1d1af1ac8523a8968faa007dcd579f048937f2bb7a388a158f565b3338e35d37f455d2d6861ca208183bea0dbc271c1b2865a38476161513c4a590807f8db6f2a4de8db1e9c142a8a15349580",
"0xf90211a02b207484d2fd6781a1e4ae62c2c4171477bd5b929df2b14904cd4f36c61363cba04cbd3a34c4d4f60bc5590d8b5859da8ac83ea7a8a0197dbbc528434651b0f748a0beafa9a7e0b2073100526355a341de7a1a839c7f7322a594bdc9ed4d73d72283a0249717659c4e7adda14416a804ba5c9b305f9da2531a3ff6e6d74fca6380f4c2a09b5d4bcf5c805d1c38f283bca39ce28077cbe0daed23312d666cde49134a4d2da03930a91cdfb11a85632972832202e0ab4027f78049f828a099327513be660ed0a0ec6a17d51d787c382575d6798093a015e8383bb276b6fb291d529498789ada09a0f54c88077fa118092db43a93d89c86ec879da12d33e6e5dd89b10b7fb115bc54a0e1a3af76bd6a0b1f4419a62bc73439c641c612a912dc8d190e8e81c8c15dd561a097934d75e361d115ea93e2fdc0c91a54d59414f0daa2ac1991b6651ae6571f9ca009abf1666d7d9202849314692d5ce1e51e5629727701044b37532ab3f9be50c0a094561fbec829ff4807911e0169bcb59159bf8d478fe7116cd652c179c28342f1a058ea9466450f42b25cc3298911ebeb081b6bc73f3c414f0d36244d331cc18c5da0697343bd56fce1c2d34ebb3baa06b3f5aba4851e3b60436e545a2616ef47cb73a06ef38fec665b8eb25934622af1112b9a9d52408c94d2c0124d6e24b7ff4296c0a0451066ddc0cd1a63e22d096eab595e74c8e8509616650d76a0eedd35f0c228b180",
"0xf8b1a02a85b6c4adf828a068d39f7bf4115a4544ebf32e007d63957a28ee21eb8dcd57a0344f34e01710ba897da06172844f373b281598b859086cf00c546594b955b870808080a0525e7dd1bf391cf7df9ffaaa07093363a2c7a1c7d467d01403e368bd8c1f4e5680808080808080a0235db60b9fecfc721d53cb6624da22433e765569a8312e86a6f0b47faf4a2a23a06c72cff8105f47b356034e5586745859f6290eb366bde35b9e819af9dcdfdd8d8080",
"0xf8719d3da65bd257638cf8cf09b8238888947cc3c0bea2aa2cc3f1c4ac7a3002b851f84f018b03235ac0b3723f4d6c6f61a0f3ea73ed7d35e887e1b2b8ac13e8645eeec0da8210c16da47b0f3b0894011c3fa0d0a06b12ac47863b5c7be4185c2deaad1c61557033f56c7d4ea74429cbb25e23",
],
storageProof: [
"0xf90211a04571622a123ea7cf0d9534115e5e6b2fd058f94306979a373b226979a8c83af3a0293a081f517366f69769840098d809396caf7ff3942c3b16aa641b23723301b4a0605ef8aa3eb98c75406d2781067f9d55804b4cd981614aa09f9f6cb0d87a91b0a09d7f20c3afe36c59119c1308a6d7a3efca7c6588acc14364c0e70b5f7f5ecf97a0ce1729eeec5fb5d9d3fed295e469da960bce62cbbd4540efbb0eaf470b0014a5a0a69bd31a7f4267359dd41b93f03b949bdf4de072651b6929ea4e756bc6f088b6a0801ba6fed2d48d4706569a62678fb93ca48dc159fd8659b7100bc4070e3f24f8a0a58273972230f9ef6f74f1d3d1baa8795f82d0bc2c2313b7522a35cfad25ca7aa0be46e098b427907021d82e9d1d45ca4ef6305e3adacb71683f94e4656718ba14a083808d1c8c0ca4a5668cbe6faba42d927ef8df07f3581d06a9381084f0590defa00b6eaadae4a3d219a0e090a56cfdb17e31326e9d60802cf3a36e8ed0f14490f0a00146a284e0a8245d2c1f51ee97fdf9f4231caee252aab01fcf3c4a619f39663fa00b68dbe3928080b43cfc2533fffee4ed91abff24109f08a3ba26e8aaae18c7cca0345de27acef95642cf996a0485bd0242281c7ed9fddd6bad6f55e6bff04588afa092099ec8d9e6dfea3ee5fe4ce7b18f9e513cd7229f7a8de6ebf93ff5ce757232a0963d3dcfec3a80dc1073eb2292be246d81b4462b8347511d335b4c537f87c29a80",
"0xf90211a089a4ed194eaf9e272c155d2e692b5585c6a38bd04ae96e487bcc231771701f98a07a7de6dadac670c4062757c16976c4fd98c587a47a687b32b640375fd7e825b8a0da765585e24133176d2b38376f362b666800735c46e6358bdb526d03f068f97fa08acba1cd699af52508c374da47250b1d2be1a43a7d25aff247ec717b8a534213a0e74be231dfa53a30bd3157e6f702f14619887946e2a447d31dcac87f391a50c9a0b8448e3cc5dd4e9728c7fff44ec252bdade1618a63d363e86e0e6dc4c77de5f2a0f95aadc2a07fb025f3492fa7d15224bab718a908b1fdecec39900f905273d8fea0b76a4d3edfbf657e6d87e2e3920b478fb8f4bdba7844a7ab23798e1bed4abccba0fd70d97eaebf9d1b9e65dcb960bc1b7e96b03a40dfcd490ebf8bc5bab8c413b6a0fb3fecd1f77557f554c6d22b86e9dfb27fe644d13c8e53c24b64e7b3f3791cd9a039cce3c9632ea42f008bb8fd3412e94dea053d4a2baa41c4a2517b34ba8e4405a066b4b4db0e22d9fa76395494b571b7c0cc1cd18ccd332e8a59bfa03b2be2889aa0a80a5acaeeb595a5740f1844d32eab4d56fffe53176c21a464ff34a8cda84101a0f454d635fa0657c436c5fc2b6a071c62e4c01c139dc2ee544dd8997f2ee9242aa07fa5c3c8e2be0f1255f49383046703291953d29debf61376f862edd3c5b4cf76a0a30f1b5c1c3c4b307a2ac472c81f79283803e88403a5ccee7750ce7175c0b0d380",
"0xf90211a083f3f2d187ac7939ccbb8690863f341b252909afec4dcce275a2e7318e1f15d2a08fdbf9e41ea870a7ec2aa31ce43a682b8e2fffd0988bb934c03dc14e1988952aa04b9e7db219d192320bfdac399670cff992e0aa5dc25d2f3de56f4f53e5373456a07f27f9e5efb3a92a1f2f3e6d8fd4bfaf9015b9fdad8715ba16d30c211aa0530aa07cc6af0533c32fe1af0e5d4b149186970040ac5c69c2db7805774a65532fa064a0f15e9c0dbdd4f935d3aa719506ae1fb7297258d18abe03111d9e5221d6bfb8cda04572757dae6365a28b493c63503809a9dd6927b6e6f11f791e9c2cec92b80513a0d1ac01dd696504ca20c087bea731dac1b8c48d26e5dad36d80e34496ee20b46fa02d879c981e1706e0720b3efa7093308a499d57ccbf9648cba78026b3e7883795a03f007ce733ee8a522776e46bbc5dd28ea33db0ae4702d733926d83b28c4d0181a01b1858a30125abe3a401112f676d6a4b669ac9495b34f89691c075ec7630a45da09d22b122a2fd0db8cc2397c0c8e05fe317e3bc8aa407af8b85ca300d9411dc0da04ad97d66e54c7a2a76bc6729384080115dc3ba5e6a7c5269470372ba6d22eeafa0dcfe09b848078f66db11284e093991436f85ef26ddb3dc2efcf56e4bf05e6101a0e641c7a710a5b8a3b465e05b09e4868d9e54353b50d29eeccc9e829ea314041da063ba309481ffd1118153e75496d66bc7a96d37f32c63f4e731e56abe4fa5f12880",
"0xf90211a00a62828ba9909a92bad0ddff29537a58e176fb8af1d76292813a72f5661ea282a0f037cbce7cbacb3343cdf899fd145917e7cf18deddf5b2d8a94027968f9f1624a064774630a8d992b0888514b5e1dc2fdd37b8a214e6bd39d3689eaf74bf65bf68a0b6ee7661ab782818ac639c03784ab65eecbb06d79d251cd8c25627e51ba5b94da0c1dfabca29a2ae57d88e29f0ea94bb3a825d4b884c7f088ab4261b5900635ecba01bf409b8577e89fe49afa62ec117c32a9beac5f8e8cce54adeb3bd501c15cb80a08d7b60700564e51011a00159786683d707b676f41214b3e538b074fc79484748a08e58472318ad40f9498b98a599d260a80298a2cba39cf45d0bff8d91ae2e4852a04443244bd4654d707e3700d112783b837070111ba8a2f0f11781d623c3990754a0750eac11d5f2be0746f87df3cf9849ccb8f13c831936a745abd37fc464d758eea06311c8c2cbdfc4ff1a7e550477cf38ddc35cf57579d0f842801a9ad6fe50c45da0c6ceee02d855cef0db230d186d9e37b8777b8313a22b3dd6946143da503919d4a08669ea1760b9551901c57fd56411368ed8de861bb4602d26f93005d0101fd195a0285993aee29c28d2239022fbda7df02d06082e0246431b7671edda601c6e5cc6a047bfd76124562bb812ec81f5b286e09907eba7e9b1efa72d4ac7a49b82eed957a054bf6597873bf09bfd3df04d4fdff771c02f9d728d51ed1ef00f6b053f3282f280",
"0xf901f1a0c5a1504268a750c1c90b7841d99e6934f977193c72d44ba456fc9a263fb3ea45a0924bbfcbd6d2e7a3f9bb5ec1898a1ec0b98880f747991e96696bd0b565e1f83aa07ccd4b2cea9ff079bea41f9d704c21e7f9d3fbaa83895f34970585873d5bd9e2a0b2e313a02508e8a0dfa115612c1400f8cf9d5cc23369b6aefd7c1fceca7dc943a0e19964c5618fe9f1f590eaddc17787071442649385109b9324beb8bf51a0d2d4a0b022d54d33a1c62278d7784996fddb4c7dcab2fc3c2287c6840edc3762e3d034a0a8381f53de80c0d06ca7288457d82fc1cef37af3e08abbed93a61d48d7c9ca1ba03f916faed29b999d16e22fcc2ad463681a42339b24fdca5a1323b5e55d5650f3a0eb6adbd0b998ec882b91b44ab6ccf20050962c45b68d4e42d2f0e3e1c9384952a009190c615b4dab60e7c1940f2b3b87e3636a655b29dd8b65b99f497ab4fbc395a0156deb01c2c14daf7c043555c077b4af3c5aac031d75cf9e4f704280983c67c8a09dd3b43b4514cfa57218538527defb69638f108383a9d95ad07a296d30bd5bbf80a01316d876cd6803dd122538f308cf116b79278393d979769a121f8354c925cda0a0324232c83f8194263838f7105b67fb93b805c027d6419a98f3c40937b9502132a0cf19102ca5c74f4e088ca39ded150e7a9d5d1bc5d9263012c7e843dfdec8386580",
"0xf8718080808080a0795b2bc0fec80623a0785ed76761d1e9abbf37b806b4b1664a22c1dac557d79080a09831b7f896628cd55e9cec00f168d92c748a1dae2fc55774f0fdc80ae64294a08080808080a020edc6edb75de3cfde19500957b220fffbfc581e93b5b6e307fac078a8b14783808080",
"0xe99e20e18d2fc45a3ea90621b218552f932e0a2a920a290d1c6bda98db9ab133898852ab3594ab17a60b",
],
},
{
block: 16212787,
account: "0x9467a2d9c07cebce3708ca32eeb2b9219aeb31b8",
storage: "0x000000000000000000000000000000000000000000000000000000000000000a",
expectedRoot: "0x16b9e5246ca2dad361d440d5524cb431ca30d0575fc21f4e4242f7611fa2a212",
expectedValue: "0x639f404f0000000000031d02a5d2b33515ec000000000000072629ee1252f3a0",
accountProof: [
"0xf90211a0aa686b484fd06fd6a76b4b37cbf3965553120d61b93dc354e1e32e3442fff947a0c8401b3aaef041fd79bcf69bc8eae7220b1932973d088c368422b43e7fa99d3ea03d14c01a86a93d483dae0f088ccd5f64ee3346bba6590bedcc6ed4975d36c0c6a0c64f3e49789294f22c3cb3bfdc78406933b8a47f743de5c999599f814cd8d166a080205a023284e4f9905946076d9dc0c029fca1452743becfba43ae49b0c09d18a04e13c9c6719f3519cb7828514f1b0e393398c7dfb0d703980062e52a3faffad1a0e806c685e60d3b312f1e740422728358f9992e4b7cf62c904c8c01265e88fac0a0f21e7ee12a407fe11cb0950f63ef5dcf62d26fa599f40136ec057c684ccaef73a0bde4594be3b1be7c4312c6ecf81ba8cd8057331563feddd4fdbabf3c67385fbba008ff9a89a68d8a8f6cec81a8553ff72043c4dcdc1ce784874c3fa5e76916f4eca01c5e489af3e55abfdee369a10075b761f58be65d5d589742ca8c6098db88e9c5a05b212b9a9b393541dec0d34c4908a194ccd8c6a21063429521308840c8b66d32a031052338c42361d910eee1c3ec4b7be3400c5cd97a7f8aabd3f5ac81da0c8395a0850317a18f8494eeab20c8015e5d863b43587a7dd3a7efd41a921ff62de926dda09e6e76b343415cf3105ecbd67e99f004b31eb7123f3e3a614ad808557d78c34fa030915874eb78ae682f3d74a727227fa86b204fa367256fd4a50767ed4c35bebb80",
"0xf90211a0122c3b5a88702fe6bc3d3464e903d0d1aababc35f259eac6b9111e5b753de6a0a0bf670757a4652ae24e5bd2fe9cacbdda79924bd6091330b950b1473dfec103f3a090ee1dba46441ba0126608d28b0023f0ae8401eda749e90d8550f2d3ca4ccf1ca0deb3887fd765e1c5db19b353dca2ece691dfc2f2c7c0a1c298635e3264d8a05ba06af91d067bdae7d64e34b2d654b08815fc43bdc4193482e9aa58e1fd852841e2a02518d875bdeea78fc832724ad33bbc66a654a1670c6bdf544a060941f90a31d1a0d7e69dfbfc026a105ec5ec68062c6affc1115ae3ad7a70e4ab854f9c914f2cfba0611e45cb73f473325c3d0ad494927e1d1053614c17cec3dd04161248305b3c9ca09767470f4299e3dbea4978fc989ca44abdef26602e3351cea0ef2885dc0e66baa060176e7f197f28205684e6b5ccbb83c5494ac86ef5483094fa3480728b11bf63a0c038f27c7e94887708465bf77ff37de506f5cb29e9a355d4b16d426e12f2bf59a080a4b6849ca41469ec77dba2d4d3ba0b0da9a36e5a6c0451e588a31af5981179a0b7fc37446eafbe040ba963a25e907af5a5d1c584d31198c12e28499a8377b249a0550e5984cd4ee2beb3b1d2af589e0a4954d8da7167896ac12985e1d781e3e98da098ea9d1574fc5431dd7342ea8467c5369ddee70b33ca37f30230e21d9a995d7da06cece45972cba1083ea30c7563c9639d398749575ec229e634f79e1ab637dd6c80",
"0xf90211a0a3afae41153cd80f43b9b413b8fb57481fac6882c1f6097117cde8f8aaed059ea0730760d301e2b18a9cd4b3f777d91bfff8424bf64c05adceb8160532728cb699a074588c944add6aba03154d7bd8b543f149dd9629f46d8da52abc9e41be988a74a0b8ae67ef514d0dad520cdc9103c2702ad40a7b0c343aab9be74d72d568902540a0345dfe1d6b3fbb5c9d0aa731fb083d5db76b4dfe22d5b1a789c78a921589082ea0cc5c0989644c549f573ead05887340e201e92f7a5bd9cfe7b57e3bb46d47613ba0002ae2795f3286b54b45e25fd66ed6173ba4bbe56393f7f27407cd559a2d259ea018cce2547825efce8cf5e6fe14d88cb7899a1d8768dae861c0e263a06640e5e0a05a6a075ccc448ab78a34ed3ee7d56a1b179a046be98a1831db18f43637638d04a0fe2b2ac494af3af2c28198dc97bfd165288108e0d2eff941cc5d115461c799fda02d1de5eb58ae72173353aa94335766bb360eef79b6925fe5f254f0e3caa8941ba0b63901c2fd1c61292d32f049dd699bf39c4019b1ac7ab12907804a1633d288b8a0071290317e54993ff32e0ab04d28b920105eeadc917e44449c4ca2fd80adf9aba0fd86afbc5d8ac6357d6ba6f13f0d08737d1f95d49bc1ef1d19ddee3dbc4188ffa0b1cf7db5488cd60ae077821f0aec741b51f8e8c553eaeed4524159373aa98d7fa0c695f9be60487243c29023e469d7af9e37661e325a577247516475e51d6757de80",
"0xf90211a090b58facddd3e83bdf8b1553a2c42b07fac5c1da069c73be25f30619088cb480a03867abbc8789869f4b7b5cc4799980299cc3012ec7fce70fb7dea2e5995a9a2ca00c3948797fbbfd4879bc72b5ec1eeba993bdbf4f8b39ae8f63c94cb2dfb89916a00796ca2b7894372e41a3331413a5e776eaaffad05ec03e240966e7ba8330f045a0713935c0c8cfc67afb8a35c948b4239710a5e7d61b5bf9d4e3d6e88e4e7aa28ca036caba99dee8e52ccd1ed12972e6c3ce4a28e160bd7542349338b692c27b5a51a02d1d87889d5e1c16690ac8b7ff3642f6814e42fe6cd6e00e108b759555f2cca0a0cc4be174afaf83b4b1d4fa64374817759956315fb684326fafeb238a41fb0ec8a09dabf40050d9ed69f994f8b82f14e037dec59c6a2a24a9879e184b546ea71448a0c77815db0d8d7eda3df1b8354ac007fd93f6190f20616e7b93259d89f1b0ac6ca09c105e9c25f2f480ef8a50c31bfdd0eef120741c9a1caa6f2278ab7fff0e4651a045ef65a0c419433050e6cc57892fac712cd3cb835da30f2f8cc249b872d6274ea0a457eef99c7beaf2b365cfac520db40b375a0707a0aa7bf234a04ec5746e7daea0e4d2b13f79715813fafb715534ed0d1474e044c7521694ae3bb1475e7d570f42a034143e125fb181ec980641ba63a9d19a005eca2081bf1e1e77572c172c8481cca04747c648752a28511842c2d63410bc6a554ca6d13aa3541edd6e7759ed62b2ac80",
"0xf90211a02cf6e48c3852fd7b3a31e6922cb756425da526a164faa2b32f19b21187503ce3a093f0f615e47ec246a5cae41dd6236374287e3efaa9c17611bed4f2621f5ea7e5a0d6c55b3818c48f66570964ab6f184094948ea1d808d26a66a6d0e8195674d143a0ac7dc18dead02fbd3763e5d5fee4d2c032ea207df6bdc26900f0d10ff2c47f8fa0c037ea2e7608348529093c9b9fec3b32d8288bd0b6ac3ae242443f4bda8e9eefa028ead29005c86ca93d969b2963b3eed06ec81dbe7c7c3064d79c6aa033de3246a0f24e9a73c866d6e7f1d411e98da53c76020db588f4b214d44ad6e536d2b7f1e7a0207fd73036d92ceddc5da5c0504448c6c2704735bc6470d10193861e15530708a020f669676f97c6585f7cbe5e405c4f9a4964fad36fe4dd6aa13c6b80a60d901ba061b56b1bcd12005d252197b44f28f611d2cf4448ca57784a8f17ac2b23cfd519a0aad0bfda854bfaef052cc6659d84e69e4b0325e6b8fa394961694e2c3b758203a09da958cb8bc74373e66cf40708a152f31d2c6ac305fcd1af07a25e3e34801227a0edfef4c130b1198a28da1ae2fd66c33d2d1e98725424b9383dee7136360c7036a04c64086b040c6a3701a1b2bedead55797c95c5d635699e66950fcf9c6215ee02a00320a92427efbd2cbe8f70c7c74aa5db0c145b75148808a317a2ccab2cf437f9a0884d942adaa313a922d0883e8139fc6a92acf16e95d2c7d06b4e53a08fdab69280",
"0xf90211a037049228c0254f0105b8f461536b772d38df8e4b8bd7f908be72982a86a35961a0d23d1b2a16afe975ac636a8720e5d9fe14dd999e47f5d9e43fe86b2907134705a086cf6044b7e6be2a9c312cf4bf438d464f111fc19fc0abf80c8ab31644bebd06a05bc25ec41da09b0c76b897525589bd03dc90b482ec59e6a1ff14102217f2cd6ea086e9e5952917cf0e054e0e00e0085d7d3bb6a704e55ec5739b6705e4e6539d9fa0148e465f1f1f6095bbcb2feafc49ffd5f604b7439f9b4ab0437f8cd7acf1adf6a0bd2bb1bb25bf43758ed57d63ead3a619cc3a94d47be1b84b4208b24f5b80094ca037ad5b50e846bb85482548cc5a99a03e1db02aadbf61f1380f61bd9ad7ac4704a0a0967620f115f194f7a0c16c7e13492646507ac7dd8553e97b7ebf416228e1f0a0f42e67ae7d57f618596858a5a7239a6039b0dc751d42dbf47bfad47a36a5a59da0efbe74b7c05b343f3e29d1fbfcaab58789c99cd301b87442363efa0a2c7a395ba0c8b4d32dce4b607dc21e9c4ac3ed9757640c760582cc1ffa4679c4dbc2b2e0bfa057addd95ffe7c0de9774f2e3790a52f262515fa6a2a65a9fb785451a6e3ad2f4a094d55a6f5ae979bfc6c6f59928f2850206c5af3caedf39386939a053a2c7b79ea075b8f0a832023c355b067f3786edbea9547211d8cf2dca5f89f9a413b9b525c0a0757df921602607a9115e97c1ca0e4acbf0a2d4ff3bc6e7ae2b151b88359f190c80",
"0xf9017180a051c6427ab0bc0d3b0db47b82e69a31fec1670e8ffe2ec57356a512c82083a6a5a0dd0af4a616a626aea8529e07f9017ae356087c45c92ef851aedd845987cccc46a0457441ca9402fb91326638832a9a169e021608db12c58d0e7778c1b13add1afea0db1a3351b7f76cb3170ecc91fd0c687ad46378dd392944612f4c68bb9fbe1050a000c1cb0f8f7bd89d04fe5ed1da96fc769c67a27b3c822a8653397e7da6a04730a0b63f0c4914683ae30b031264fef21806ac7a1a32ccfd05c011ddd0202e06b275a0ac66fa130cd31b0e4b15b08965686162a3efb93e3a07ce45859b34e9a2b4112e80a0dfbd89ded3590a54e3b47e540457b06c754b7b0d22cab361a79adbde4e3d96c980a0cb72d7bbf7aab515231c32e9399359c91aff95accd474e39a091fa2b9e71259b80a04a2be13b00b2032cc0c7112be04907d8d0fa0968932abe8dfdda6c6bb07813a680a010d29a9d3186ad1e4ad1c518be391c44180ba8ce1db0f09a2c9ed23ea017733980",
"0xf8669d33239d97e43f5062453663ffd198f40e6120b1057a77480a17b59f8d8cb846f8440180a07a5f002403d62f9d1ab5b4684459d1a2e5170075efb41f51f94fdb30b5e6d46aa073f5b0f762a0557ec4b135108e719884532887167fa14c0d6b7807943d70d96d",
],
storageProof: [
"0xf90171a0b5a85440d5fc74ec55facadb9dbc0cbf35ae1eacdb841b17d6943721a7028fe680a073d52ce999835ee363c087004b4de88b619f66f3dc94d35be5e0b17869d7ece2a042bf377671e60c1d6aad75c93a25c72f0a0c7c2fdaf732b1ae508dc937ebc0be8080a0a32f55598dbc06e6742074f3ad6812f923f9a9f991e597763520cb939c5440df80a01a7798f0e3bd3bcf90d8150e03e9220c1547aa70037856b2961b5fa8dcaaf974a0fed5524862371f728f0e99114f0a09685044436cf34c22cfe4401ec4ec03ffcda06bf06cedf7b90669bac0f199b18bceca612452bb315f1386645bfbd52205a476a04d2c61e0aa8cffbb121715c333a6289570d450cd77f44d327212f404bdc932b6a0af144ae5e9f31fe6da35eac694185fdf07aefb9da7f4c652645bd7f0c7253e85a014f49d31860c00b7dcc901e44c39f3050b2e3f3b8013c0af887778813da9b97b80a0ce3ae4b74569ec95d0d116928f28245839a0c0629d2ec86081ee4896f9a2785880",
"0xf8518080a08bafc792d182fe0cac5c7dfb236bbc88dfd0ecf5505b681d1c256d75aa6858fa808080a03315f891bf9433a5415e982ba0f5b3d4497a2a44cb9a958d0830fe301fecae4d80808080808080808080",
"0xf843a0205a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8a1a0639f404f0000000000031d02a5d2b33515ec000000000000072629ee1252f3a0",
],
},
{
block: 16212808,
account: "0x55e617b7456abc2545cbb547e0102279a6c430c3",
storage: "0xa6bcd7cfb5e938d75f4330a273812b53f809408efd4332627beb0285fa4a8732",
expectedRoot: "0xcb31a10f1562c0c36bd4ceadaa95dd6234fdc02e8cb9357339e507e6b24584bf",
expectedValue: "0x0000000000000000000000000000000000000000000000000000000000000001",
accountProof: [
"0xf90211a000cc1eab958a3f1de15398fa2b27750166c045e8eceb809b9d4501b4e02b7ddfa04da48723172332e782e1bf0e4fd8b1e5f98401d48596abd9a9705496167d7027a0dac4dba16da7ed6cfcca82063ccfc4f47b6fc53451538f7d0d1c7938f038940ea046d8e39429c81dd993f99d3b11ff4cda11bb8c8696b9d93472e71356b8041832a00b940d003e8cf026d1ada0202aa2abcae53098c85486eb7a534af6b3004f8443a090045c5a2ffd3bd39f80bdfa1d6e5fcf75105c81484ddfbc5dd4b4d73f6b66a6a0e4832a0fde78437c8fbedb522d2910e707bd1cf80f2e10b9c6040da0b05105d6a0a0e93dc2989f5868d5cbdd62ec70157cfc4b2064daff79586208e60d68221aa4a0fc7fb69a47e3d6b002c776b83f17fe0c9afbd922544e49bc69118d4912f814d4a0521e58e73a9dbcef30b0c02af1283b7907abadad2531687321fe8ab200027879a04d23897e8ec61a693cab8d2252fa69ac45731de79e47e40711c363b1e7062fcea0290185b97c0ee9f00882f0c50b493205d1a22128338dbb6bc7aa6770c7badb8fa090b9f84dc7ffe1e953274bd3076e5ac2c6faa2ffe8335a394eafad186f9491a3a07e8faa0688cfc77a7cf1011832d69385499ece50ca53ed08fefcd4aa07ce4409a0dfc42b6dac4d479a49a3d2d18ccbc5bd9f98f055294ad62cab84cbc6267f85d8a0b2f0f894b7cfd6834f2c9b58cd5941c8477961169ff6579dbf026a28a871ae6080",
"0xf90211a0cc88a0d04fc4367ca945630ce6266a93178092ce38ebd0d3976125c80d9e638ca0110ac16b660ba8dfc12258f9ade49be6245e7d229c4b40ad947c2bfe584a5ddca0b7884a63fdd62c909b9325f29ba55203c8368eb48c420e950354387594c4667ea01079982e5d8a202ed036f8bdd6ddc48b2eaa7c3e8c6efe8ac3369b997ddf2179a0210f2400b4faac315689001a789a6db9313cd835cdcd31df96eb65c433b115e6a089bb0553166bcb16346053be885e361d2d67cab44f7b959aa9cd826dd45ac61aa03b87244622f87055fd869434afd48c8b3ad5a9607b747f6c0d2a5f294e362ff8a06fc34c186c23de6726ff12f731925d0c022b1e28099c6ef1fa3f19423e974396a074eb379a4d71fa80108c16d71c9c9987bfe618f2f9c46dc42db411aa42984b78a01c679db1c89150fdf004859b6a69bed2045f4b8731b221e4a07eecf35539eb5aa0e5d137fd960b8cbb20606bf9e7e9fafbde54c409d1c4613dd80a17de5b47bc5ca037f5902b0eefe2f4d3a498af280683cbb6e24a257548f49c8a5541269da4960aa03ea41d2be7cbacac4f8ca44bf03d0bcd589a01c10a0bffafb8fb1da5a70e3068a0bb980af567ae4b71f44121bc9041c5e32d971511629ab7a40609a36f45981ccea0ff394894d8deeda5f8548486bb5feb71b870a8a431c0841886a38de9914bf188a05afa6d271d39956efa0b6a37f849587fc9ffdd0b21b0f03a7475075f3db941be80",
"0xf90211a0074eb00b4c1e2c7113935bee95ed4348415dc85b368967d4d5c4d76196af424ca0813772f3b53979306c3b6099563da22debe31524b46c489b304f5dd00e38790aa06c3522ff7176e7802c0565d7c0861d3b3d84bd4cdc335af7515cff8d08ca7fb7a0c768ae9e22fa57009ecc980b0550fdc1c0b1b4347a505cc4f2305681480cc792a06163dac89c2f3a035f43a559f71c94c2ef275974bb653c51db896c3326c460e1a06c56dbb2e85d467a81935889edc1e1fbda078896de4e9c4ffd33ff780137ce24a0e0da97eccfc2ad11d6489af5e6c646bbe8fae20c85fd1614e84589ac69b7b110a03eb954e27f07ead9cc4013f091b2b3fca8163d3ff052c6a4741d7b652161e4b8a0d1318e44803ed8fb732a840a9cd71eb2d0dadf601f8b8b77251b6de06776513da0a14970d414825f655862751df3bbd7fcbe9903adb663690cee115b4fe880a7c2a02cbead1eab47e6575d0d9d488311b4f16199fb8acabc3bac662c698d471649bba06acca947c81f7bf0b05c8218e615ed3642d1e812c3c696b76d19d9e95207ff89a0486a337786d2e2c7b3e963a9efb9216a79ee5cf61675b9aacc9cf3f35c403559a0e3743c73438b616f23323e8722d90afed16956be9d9763d35968619ef644d893a0437723f6d8ed5906cfc7f1254f80504c15f394db51148357f4c7ef0ad01833cfa032e215e323cfca2dbdbcf7056012ddadaaf9f8b9a4269f451ec28a19018fc76d80",
"0xf90211a079d20a2fe4ae7cb0a24db95f0cbb8a32bee53ee9910a9fe8959cea9d6d584993a01a486e762c0b7f5e99f02596a5250acb7d6d54d2626b7ba6c23d97931cbe3296a07b56e82ab24b02849378030bdca3ae3bfa19af23363c731537da3b47dc64c299a0a3c947fac18c8907db5321a2cf28e6fa0205d074db959c12e25fd0c9c64f64a1a09f658920397018751aa15e1feec3ec81dfd19988e590b663c6efefde407e2a3da0e5dcbae4c0fc4c9a050afb5ab81b71a76cd201d9ad724894518aecb7ae557079a02eedf89c6286ad0d5a8f24ead4c300646452191765d86b7217b7c503c9d93bdfa006d8c0bbf530c40ed8bcd89dcdb4cba927d3363c4eeb3fd7452c82f986506630a0fe7850edfeabfb584ab06d0a1599d64ae60b143cfb3bd8bd1cecd8e918b0c7f2a0d09c9c7f8b8280ec01c8fabdc75a5abfb9600e5961b3f1a2e62313e81bac9d26a03c5944032432601c395a4a4c31c3feed3606881df80407e7c6e45a82455f85b2a02dea3f595f1b07648456f39b39a6b337d5903373c5c194da04ecdbde82b40b41a08cff9a982b8e0fff7d588cf0fa0116f039db921c13fae79a5f7e8333ad4d3a18a043dac2f48ff878530faf63341dbe6baef3faddfd049f7db4c183079c77916b17a05e15585f071142178813285614aa8abd4c65a95f516df528ae2d3c6ee08521d6a0b0dfa07c70efbcc57f2b6cb7f77a7a20fc9537c0d984a676ec9926e55f71c77880",
"0xf90211a0fb721ad628030689ef65168ed001f566cd190e9c4d0219c02afdaeb004d4e214a051531d55c79e21f006c4741486cce4d8a6e613d761b3bde9ae2c8040a76b307ea02213a6ad7395c88dbdf89f0b29acf67c6aa1dc0e374cc6a7d9b6ec3d9fb5f373a0686884cfda50455fdff45f4170feee963de6d591770c269f4241e34563d70f37a0bb97314a2c0642f5abc066b8d53634887234dc37d3f9538124fcd27225b75733a01a296ff7ac3bd812e706959caa4748f04cc0729fdfb14388e244347b4a3cb685a0888eadb1b0d48cf03e73398f2aaef32bb4ac265f10f76c504db269250e88fd55a0b9a2aca21bcd60c94c2a80fdade417a56fabd041b6c0379159f02ff2fec8ab87a0db49371306dcf9e9d4ae471429c2bd4affe09cfc065792ba6410595f8beea2c7a0bba4db70589218f90ea48d1f870db783f8aae6cda9dbf72235e1284b97313dc7a023658240a8e60035480607bd2e2c780d0a305909fb06e9c6befe7701e78b596fa0d6f93b95c1fe2238e73c72e96cece7d21189e5c8e839bf0d42bf226a105c08ada08ccf4640a918ae9ea713e739e62f7b5c5bee3864b57c32e29065593cc8457171a0ad5dd98fe06ccf15db195de3aa8d071be23965c64839e10d1e9721cd64f26382a0e5a987a544eac0a3abc6ef9ddd12d8450b3e11f36d6239cd799595535ea0431ea054db8f7995108a2c8bf8976723682ce513241f75da97518991c6b77c050d398280",
"0xf90211a00dffb8e3f1d162560bd7fa2851c9475cd30bf41c78017372b8f5d40360831308a03348160896064725af3bb64dcf86a8fab726fdf442007fd3825c689553a314f8a0794309daeb0692594a7bdd16e884ebd75d598db16cd1005a9176fce869b3580aa01150f6cb195cd24622f9440d2ea824b33601d7d7983db0d925d39daa1695c950a04b61b2cd4bf2ec97550c27656b784df083bac7653352920b3bb0404bb09f1971a040e09010e7c233361e66eefeba4c03cd551580bf394ed6fb6cb8f921184a9f95a05ba6ce8c14236c7b63aedcf3f85603846062c43d165c207cb5418cb7f06dfafca0fb016acbbd9d14aa6bdb9b01e802ffe495032e97d124c9a0b65d10d4e715f39ca039c0a367372d7a14a34ecdc997bf67bc72755b4c7270effee6d90824aa15b087a0c7ddc7fc8c0341c56fc7e6228469b25f7af926b3fd099530c6097a02c869c41fa0ad11f0c6cad46f32f1ce178820941063777e2871fa38d5adfbd91672479213afa03b11a8fbd61e8e0f3f18a7c3573ec7a792edd83d3a6b8efac10ebb8b157ac17ea0ab266aa84b02ef61bc71faf1d261e2bb90cc21d6cbdf951b122f596f5eb3d90ba069b80832c46cf88b0ca1e64054d87f2e33f27df1f322c70af89f4ec909313bcea075068d344e56b3eada6312fb613925c3c9de369b328ee666121dae6c052103c4a0c3b65e68859146733573b921e8fb036ca7c9434b0f52412ac0cd169950f95a5580",
"0xf8d1a0db401bdef3bd74dec5338135194e69ab43e15aa891e5de20ef3e57cde5366ab5808080a0621c1fbbb026eddb70a4c645e152dcf9b3f1b40b9a1bdc4398a22bee4a46aca380a05528de70186525019cdf0880afb77b33ae4871fbfaad3e8bccd7dcb6402d746580808080a020fa8ae1091998f03c979f94e94ff6c011427da2834f1dffaec815fd3c5fa6e080a0611ff1f45d926197480694e690227d603e84e7c44b520473b9786cd4fafaf613a012dfcd444d4948c86a3dbad8f4f1dad09c313a63e6f8bf0ecb7bd799908aa3248080",
"0xf8518080808080a0cf86ad50e7ed35be6080c4cd74d835e58867b2e2ec03198baf29962de46a8cbe808080808080a03a5ec92acf98ebef8eeb621707a501ed0fd95186282ab1dcf8e7286a9142b90480808080",
"0xf86e9d2019df8705960e4a0a7ac52ab662c57cddd5f60a7f75f0c117ae2e073fb84ef84c0188067eab853ae20000a0724a8bd0aaa1c991a445a1e974deecd8cfe4ba2040de2578e98238b9f963ba8aa01717795a0fbfac056a8306e5cb0ac160c3ad752357e0360a408e59acd35ebb1c",
],
storageProof: [
"0xf90211a06a128b938cf5a3be9f5c7a8944945258db0b7a939cab65a4bda8fc4a8a2bf16aa0c61e8e76eede0e8a446743dde629574cd69dfe612aa0d30c6c8cafdb7f445214a084c1c16c0f4fae18501251afbc28ef21caf9b2f1b5a8f2f0b6b87d076f44f7bfa04ace3470f520e28ebdfa4e98a5ef51af05f647a3d1585f0d98f3393098839f17a0d0628e1db39bef70e79ceb5860a14b34b78eca696ec7910f3bfc91631a0abd50a0b718050b33452d627f87f02ba8b05f976e7eeb2c81cdd445770eeeefba236fa9a0f0a8fb4ce1456839b267d76b94838113ea18600fefa3617733888b1ce7da7ef7a034dd7e5a07aff6c7d141c66b4aab81f3f31363a92d48a9bc1fe072b94d69bf63a049c1f246035c714f4d6e8d81e7a20aef93140d067012314b37489a66f4e19db4a070279280c8be3e03684124acd488d9611ea5dbf62512280eb352980ec8334436a04e7d88090f29162b58e6fdd44446f90c5bc1c39c377d7c757c6010e9a63c738ca05eaab99620fe77019cac5ea6854f3efda933ea60f1326ecd03a32494850556a4a06b4116e3177b3012c5e06ab564d1a0611140ee2b81d50c8fd8c5aef333296965a00874454cb37dd61c28f8bb7da5d905f5dacf0b813914099244b65f536561e22aa073f2018c86cfe905a5bb8f69b43395c949714183a829990e0e33630431af8f86a03f36076859c730c0f5851ea263b5650dab7235f3c8ce258f74a3ae3b7d38add780",
"0xf90211a036c69f765a83b393b27f21eeb941b8a2965ec7d436b3965a5bc40953a32884c9a04fd94c2ff0df3a8453b14a36a55ee9a15096180c12feaddb7c904016e0250491a00b3973a34de7950e6eed8e413dacd2414ef22a90ff9fd322501301e159a2c081a0f6926e67b5dbe04b3991297ca0bd8f1fe63b1f193e16621c901ac81ad9c25a85a023776d17051b8899483fa00c050cc50eae159dbbd7b59a35290b6d6b272e07c9a00900c56dcf2ae9bc0d19ec918cbd7fe63e7afb8aa2d962d1d5cf5886c763a7dfa01e52f9000865a4df376396fac674f061a61603647923a3a577387c54e1b32826a02373c893c5feb4c772f345f6609f9f9a6032c068f2453aad191626ce6a2d625ca09fdcde9e12f55bd9b3bfb323f1c9a7488f573e0b01d829d6f0ee716e92f0f248a0353975fd758f23275ce22c485c939c781ba31aa8c6026688931ac61d0f0d8013a04f0352b630e3ae315c64d02f85c4cfc255524b445046426c3e67f6608a9689f7a0d3b728caecb48e019db5f0144aa081ce5954c8acadeadd3df36d25b6e24a7e0fa0758800b10d88e8b477fc17a2094b5a41aa69c37740305e1956ed558dd5dcd86ba09f51f4aeb641e8c068dc1370a71942792b4d30a572ad0c09eeff206f7dbe3355a0c5d5fa6fa22f56ac27c0f6538f94615e0e7bb49243d888ec6b0c86f61dc6922ca03b7be4e1038893b7cfeab5a172995ac07e1e90142cc566ddc2b613e3b2a08c3880",
"0xf901d1a086ece613a3028576c5e26a4ff50a9c3311c3bb3ca3751b8e52d2667b18917f4f80a0c54874707f838e0a2abf666fd3c50f900c9c0c38e9a69b37551b1711acef7eb1a0b7e0dc7b68d45f0f52e17301906d038323861fdb60583c6f505f76d304c73ea5a061a5e1481d528ed55ed1dafcbbbecc99276220ccce4ce56f50a05853638a3c4da08db8ab11699112f1f4cebece052af297997fcd361f5ceb88db4a7168e0366cdda0b1c641b80c0e5642b33866b899afc25070277d24665b6d73bc542543592c6eb2a069ae6c87a4a8692ea804b51379521e3856a6a980a1f6143f19ffaaa397c1699fa005e0523d440c3fb4654841a3d8ccce6e5eec4cd5f145668c0e95e847c9c4c39fa06c86477d3592a33fea0e7e425cef6b79610cd32b3bd17fa1318a5e20c9feb02fa0fae05cf440cf5cbb96e83bdd1828f5a582aec03edbb87e5035fd08660f09691980a0d91b6dc415a8c148823a7f865963d2b527c6a93bf882cd29da46f9a9594b4c41a03537d0ab40aa8b56059d99680365cc017a26fdf155fd6f2a7788311723b80738a0e38ba0e1b4f98b4b9f1925ca952a6a9076eda1bad2e36dbc80bc5135372a3feca086f2109580fb4d1a26bb9101b88c407eb13fade29243d68b83764716dd450e3980",
"0xe19f36c2516eb411c7c89f75dcf98d8ff95555585215a5f6242b4f24adbcb7424901",
],
},
{
block: 17654287,
account: "0x0068cf6ef4fdf5a95d0e2546dab76f679969f3f5",
storage: "0x0000000000000000000000000000000000000000000000000000000000000000",
expectedRoot: "0x6e0dbf614f46a7d99f42bb19b8d077852fe794a040ae62a4468810e3f0948bca",
expectedValue: "0x0000000000000000000000000000000000000000000000000000000000000002",
accountProof: [
"0xf90211a01d16453323b30ed0475ac6e0d8498b3defee9b0a2a273208a37ddceb5e41f69ea09173547e094231c109ca45892dd38e73edeecbde5f89585c981ee7c6ac038a24a01980107b929796de0e9cc55bb7505c7adfd297758a257cb43b9af152d596856da00db006c2271b90391c0a1290bdba55f2b615eeb5307a8bbb4c8faeb15b8b7ce3a0b3ff04cb4685f72483f12c93de3354d621695c59a324e72e09f353af209888a9a0ba895b778ace696ec60b09f295ed885afaa027bd104e3fe58cf106471c71697ca0b8521df9c6de45143d29a6a1e1f855ea11d62a30ebf601914d3524bcdee2d6fda0515cd9a8cbcb46a715fb7ff67fcf72bb433a4c2bbe53c64d0d92d83d7e4bfb68a05a12f19c558e64b1cf5f404e8ec0fcebc0c3c6b05eb5b12bcd5366fe09107652a00e5b7619cff2463f4c063e6be5d511635cca7cff72c5ec8e2d6ab2feea7700e0a09181d13feeaa190bf4ae88de86b0adf2ad55a94864245c2d9f32ccba082e3d40a00c23af247cc206f2edaa46d98d290c8b49018909d6ed97b7346e7ef69e4fb5c4a03acdc865ba1b65c64f9c495fa01975869eb1472a9e87d321a8ffb8ea4dd53a33a00522f686e138ca2ae2b3063319e01b3caf8447d19a0a00affd567e673f57e3f1a048e346e25a5bba903ff0d73354f0289cd12adecef7a50f1a5e6b77fe840c3216a099820f0f4022552c5439640dfe42f18ac125ae827698341a20fc35fca1c9244680",
"0xf90211a01ec95bbb5cf4dc39f63683626c7b0a773d55160908ec99e59a5326380c73203ea0c5a50a01b607a8d5eef6ab0876a506c461d1c598bc4836516421ed1019d56bfaa01a976d9c6cc14e1f6047cbc492985d4812b7ca2f93cf63a2b34200a8212d7a54a040b68773658d419c60e169a84ff4b45594909c4a5daf2793d4d5356bbf8b0e2fa013167a747e7a5a34c9f207f50c62c44b717818ac25c3fcc0f1ff27d7487c8504a0640b788ab79273cb8b6785d078799e71cecd9c209e26c6f870e757ab9defde6ca0de36a43a3e775e7ee817093b16f423dc995f9444a29c9cd06e2f8232254cb95da03c4820d01e2a9e74f3e6da9db1566f5e94b3a933b9864e1702666fbae3175359a0f65de5b5290317566435b695d805ae983e659c93066b72fa09d34114d7dcbdd8a09b2c0648e974edef55f325dedd496139f35bc377ed3e9be17433ee7e8dba5643a0a720648153362da9c1e5ea94416af5f0a069b493ffacbd1def2efa256ced334aa0c5cb7b88ef6fb88d93301bc182581b5680551d1e6d9c518ccbb78f9da0dbe9e9a08070a83e329446fb9a61cbd358b1a14e8f633b5980ed39018a39e856e29fd7c3a055541ec7a175eb2b357bfc608c8c41a313c0e7432b5db3a45eb332bf39ffc705a074a59d2b10b98d80424671e0fed8b95c02c63f007279c77c8637201c806024b8a0a0dd938f251e9e58f33c56842e54e70f6edaac451cdd4ff908a4a845b8a094e180",
"0xf90211a05791255edb067e389d9230610cf6c0f2b5bdba04c787cc253b4408c0de058380a0f0e14c57af008db14bbd968eeeede1f66a277fbcf33d9d6dc7d7909269d31f69a0d63b643ad254d69b440f854ec3c29d0222093d6ee5c694ae130c9a2f30d750b0a0981b82957b34d3cdfcd9677c5c3e7e51f8907de9d62f4e2c1c7daabd53e98f18a0e1c921639a76503e3499702d6c7880c3dbc49e74e4f4e3145e897382819143dba06451b79e74690762041d77f207ae889e6d0379202f37591479e644dfe7e2ef3fa0d40d43938929bbc1656e2f5ad99476b953bb32ad8c81bc190650a34bad9b8befa0f2869cb5ace3192e29664e44073af68f0cee1c095baec010acba5eb710651841a0eb9cfad4c796fa13ad2692e3036e951480afb3b168fde14b59bd6ad5080a6922a0a7d8e8298485e3f6d2949c11ab2a5e2b5f685edf92e57fff7bbaec2d289fe150a08bb1562017cfe065095f8022e9c09e0e8dca556e37103f643f4ac7aa48ce6fa2a0801236ae1ab97c2ebd3d3d84a3649a70d947190a3bf03ff2e08c9566ccb48e96a0d677f601663075137b9a84af1134527bf8b1df1c7f02de4e6509be3892aad4e4a0b6c4e67c85d79a08878b349e1cce515d64fc28915ea3558053e1248ce70c5286a0d0a428122fb8105e813924660214896ec0851fd4f33e64851452476e817e2097a0727eeb8e9ea4e62815c0f46708a1527a9ff9fac9994c1442f9c118c0be8817b580",
"0xf90211a0969453ccd835ca415f87e7f63eb2a2c3d349616589c9bea36e6d9503b1418aa0a0a73b67797d24c75dd716fe6779f8a462a1671efb1a2d1433089eb0e2a17d105ca042a06440c9d52f7d6ffe8ab7c3c453a05a0243ba5aee609819bd5dacd8363be2a00a70d832a68a496c174ca785ba4bdddd5052ca3fb2410e4b667851fa7fb5272fa0af4e35e3f9b0617d7ff80cb79e1ef0921f21a41279292176d9e117f422595eb8a0a103553baefb54481ff0ea34d75edad63879182dd595e4aa8f85ca185cfa1abba081b203264801d3b0fdbefd7954900b4165dadb47a6ea210b92d8233429501a64a0f8e5f8ae8ac56d69b2e9ab881a0b853277e92833e7067b40651719d7bba31bfda0ebda38384f871cf603a4f5ad2a265e818aa91cbb68b4de1c2e1aadef084f4ceda08fa0b8481c834c6b4cb1a85d49b3509632ae55f5d194a69c821ad9753c3a5500a0aca036de251523a82f8188ef0525cc3d2e776aa786cf3457d8a483c4d1cf88a5a04f817b7b1e70e186f6f9ab7cea8f7437f7efb3aeeed22ba6a6ea380bfcf962a4a0cc6653c620e174f2d3e3e0756cbdeebc2cbcc1aa1c67cbf1c2ff8aaca84823c8a094e265b2c06fa02987213ade5598826a29e1a24bb04df2b102a646cfcede6c90a0f021a62413e90e1e8eaa49dc399a48a9d5ec3f84dfdbaa0a3b4a419dd1bde199a0e79d5f428c71f7435fa18cc01a6484a30dd43c781a3e5f14c95136dddd5901c880",
"0xf90211a05351d3596a31b5813aeed8088aec6f64b64ffb590a9b9a675e3c24917f1bd15ea00a098a769a5627b156bb55ef7d334a364443cbfe28431e2ff28165b44cb95542a01c7661008fe9ca32f0270d302d82979c1495343c9bf25e87dad3612929a5cb36a01f85cb40320b137c49e2ecb5aa3a3db85833c69747a86f2be7f4dc0d745742b2a03aa74296d38eb5c33bca5c94195da9f32a7217349e69575b84144268e6f1b2dca062ecf298a044531b19c8beea544f99197df6e8b54219a0f27dba4d4fa541babaa0b0cd63f95c67f0597165158d09c7c27d7d8202f9be608ae26dd5316433fe7b7ba0bf61c2af584a27b46bef9a14e527e7c0c2000e123d1bf39eccd59db47ecba01da0bf89e2fb3b1941518e2eb35824cdfa1245d6cb7bfbec99f6309a4d18fb9755a6a0a8b9e450a3d15bf70d4f9a6f6a3fd34dbd7eafcff3f0acb1d1ac6d162089b522a0250aa8ab557f89ffa83d661e8757f693b0d1315bca13d5bd1fc6897912a0ad45a0a962eba19068192509edcf9adf2b976ad84bd1bcd053bff075ec7ab214a80faaa0110825fe0f439d26bb6270e37fe89e8b9f9fab096420d5cbaddd04a349370209a0c7ff710535da560b7329183cd75aeeb34564ca01447eec54590bbdcfbdc8601ea09ff46c368e03322f356f1c5c863c4cf1aed1967bf39d020fb4bd0c281c68f0baa030a7ae32120f6c0a271f70f5323b5a4b7ec7c9b50eca8e62a9fe50b47b6fe09680",
"0xf90211a005d90b43639d8703b5b46e1a300ee59e21bc329ace56f5fd40a49f8c98c997c4a02634774fbdaf6c1380337541329edb575ca40bdf38f99d22f20c6599fb70a915a02b80f43a33554844dc3ad3b346db70a2edd74985b440c22fe70f51918c6e1464a0a685cffee53f88bfcfdede63aaf73becc1f5621c08390c13b02dc9de8cfc0521a0bbd2a32a4b54ebf626031f190e39c90724ffd91b9474d841b6eb9c0f76bc8ce7a0c860455b9da06b1e69e4aa952c787761acdb1603913b4965fae684cf016bcbdca067e8f57fae01bfed4e1add6a0b9ac5641be21ddf24ef18289e87035d75b871f5a0adabd78fddeaa6c42803f81a23e7991eb611e9ec1c9071a24022aac0a71a8ceea07307279fbc13f2f29a5f6c21add5106efa24f73ccb7ca02d460196e3810c37afa0392aa0794df746a43cb59907b892bf5aa78051b45c7ca1112c5b68a523623295a0a5e09e62e5cfff36c2dd8e738762140f943b6c2c85d8b5385f121f74ae01282ca00943c8def2f6f51ef2e99cbe99c50eb5f599bccb039529a874c6b3de3e5cd2e2a082affeb98e43b37d23515983324bc459bbf503ddcd51e9457acd9b1ee47ce4a1a0a3dc55ef190ed6ba960abae03c755928f46eafd5fec04db7b78345eddc1e16d0a0d8e9e0f89f9729526f4ba732797d9bb81e6eccfcf5778cde7e99545a313c8697a097c3d5a698982821f3354cf5a20a6673b5300019af36518f85e4759e554e4def80",
"0xf90171a0d346d1b6b8da1dfb0b97f26625ef03ef5636d748d022ce03898d32c8aeff119f80a0967b15d622a02ad2992db69e49b0460151757bf3b360df5fea408bea63c026cda09c6b26a5217537924d8783f57eaca4b17d0cf7bd2803ff372ca9e4c7c54bc29fa0cebf14dcf1027078e6c58277f932e1caa306aa29d12ebb690c54c5738124ae8880a05b45f21d20b4391a22b68e2d164a58c2a80d356968dfee8650c5e2516398ab8880a0e4b87f12645c511bcb763c404a18b754ee4644ae30097302385298a3f98aae10a056cf6e6079e53f30b464df39a4df44ef33d032009b46e60ad2204fdd5ea9033fa0fe4c7e738646adc940b306191f948c0c5cc7bd694d954c945d8c766d7ef34c92a0e8c65be6abb26a472102fc89faebc972b38d2badc20e7d7b16206d4b22f3462580a080b20dc002a994c21508d73e79464af914fa6d746bbba02477b512ad0eb7ea7f80a0c80aadfec76857d1cceeeec3cbd04f6923e36334fa394d20c0fa8e0da078e9e280",
"0xe58313f4a7a02023e131c23f3ffcfdc667ddfb152602a5584a3bc89d5fc721273d06280756c4",
"0xf851a0d19a48e137ace64957841715dac64aca2b13b67dcc281c40a5d0952ac474a61380808080808080808080808080a07028d519df1e68348cc0597fe6fa3335b181a3f0ddab251792916634c9d2ed9e8080",
"0xf8639a3252ed22ad4e036cb1f5cf3d262d5438ece2fc3097ed10fb737bb846f8448080a011de7f0b3b50bbe96191c2bb22b22933a18739348bc469ef3f995cfaf66c2352a0c2d83c5e1e5dcb9487d2b2b5689520b4377d503cc54d63b144f88cb21835595c",
],
storageProof: [
"0xf90111a0845a58d6992ac45fa0bcc607366bf7f88e0d03dc3dbce12a1cc4015c4d8abdeba0c26c8ac66961c484cbf850ff321be32b5ba99620fe480648db12d6783a17078aa04e918b76be51be2f02df0ac6191ec2765d401d2229e47291806815da755f5b5e80a06d7d944d988655e1fdc697223d3c3e115d005968e289f141c94f105d86c74196808080a0dc97b79c03ff591103b4961835f65de82a94c7166fc1e390f35deaa11b158c408080a057a2faf89e4b43c431600b5b6c687cdb6cbe5af08f9380158806b7e603da7b78a0f45cd6b758f905463cb8d116e78e191d983f7c26f98460306a7d6217c62da9778080a0a334cfbd70c0bfdfdce3d0aa560293be9cd496c2d47c8508c82f210b01dfc58680",
"0xe2a0390decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56302",
],
},
];
describe("PatriciaMerkleTrieVerifier", async () => {
let verifier: MockPatriciaMerkleTrieVerifier;
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const MockPatriciaMerkleTrieVerifier = await ethers.getContractFactory("MockPatriciaMerkleTrieVerifier", deployer);
verifier = await MockPatriciaMerkleTrieVerifier.deploy();
});
for (const test of testcases) {
it(`should succeed for block[${test.block}] account[${test.account}] storage[${test.storage}]`, async () => {
const proof = concat([
`0x0${test.accountProof.length.toString(16)}`,
...test.accountProof,
`0x0${test.storageProof.length.toString(16)}`,
...test.storageProof,
]);
const [root, value, gasUsed] = await verifier.verifyPatriciaProof(test.account, test.storage, proof);
expect(test.expectedRoot).to.eq(root);
expect(test.expectedValue).to.eq(value);
console.log("gas usage:", gasUsed.toString());
});
}
// @todo add tests with invalid inputs
});

View File

@@ -1,84 +0,0 @@
/* eslint-disable node/no-missing-import */
/* eslint-disable node/no-unpublished-import */
import { expect } from "chai";
import { randomBytes } from "crypto";
import { Contract, toBigInt } from "ethers";
import fs from "fs";
import { ethers } from "hardhat";
import PoseidonWithoutDomain from "circomlib/src/poseidon_gencontract";
import { generateABI, createCode } from "../scripts/poseidon";
describe("PoseidonHash.spec", async () => {
// test against with circomlib's implementation.
context("domain = zero", async () => {
let poseidonCircom: Contract;
let poseidon: Contract;
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const PoseidonWithoutDomainFactory = new ethers.ContractFactory(
PoseidonWithoutDomain.generateABI(2),
PoseidonWithoutDomain.createCode(2),
deployer
);
poseidonCircom = (await PoseidonWithoutDomainFactory.deploy()) as Contract;
const PoseidonWithDomainFactory = new ethers.ContractFactory(generateABI(2), createCode(2), deployer);
poseidon = (await PoseidonWithDomainFactory.deploy()) as Contract;
});
it("should succeed on zero inputs", async () => {
expect(await poseidonCircom["poseidon(uint256[2])"]([0, 0])).to.eq(
await poseidon["poseidon(uint256[2],uint256)"]([0, 0], 0)
);
});
it("should succeed on random inputs", async () => {
for (let bytes = 1; bytes <= 32; ++bytes) {
for (let i = 0; i < 5; ++i) {
const a = toBigInt(randomBytes(bytes));
const b = toBigInt(randomBytes(bytes));
expect(await poseidonCircom["poseidon(uint256[2])"]([a, b])).to.eq(
await poseidon["poseidon(uint256[2],uint256)"]([a, b], 0)
);
expect(await poseidonCircom["poseidon(uint256[2])"]([a, 0])).to.eq(
await poseidon["poseidon(uint256[2],uint256)"]([a, 0], 0)
);
expect(await poseidonCircom["poseidon(uint256[2])"]([0, b])).to.eq(
await poseidon["poseidon(uint256[2],uint256)"]([0, b], 0)
);
}
}
});
});
// test against with scroll's go implementation.
context("domain = nonzero", async () => {
let poseidon: Contract;
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const PoseidonWithDomainFactory = new ethers.ContractFactory(generateABI(2), createCode(2), deployer);
poseidon = (await PoseidonWithDomainFactory.deploy()) as Contract;
});
it("should succeed on zero inputs", async () => {
expect(await poseidon["poseidon(uint256[2],uint256)"]([0, 0], 6)).to.eq(
toBigInt("17848312925884193353134534408113064827548730776291701343555436351962284922129")
);
expect(await poseidon["poseidon(uint256[2],uint256)"]([0, 0], 7)).to.eq(
toBigInt("20994231331856095272861976502721128670019193481895476667943874333621461724676")
);
});
it("should succeed on random inputs", async () => {
const lines = String(fs.readFileSync("./integration-test/testdata/poseidon_hash_with_domain.data")).split("\n");
for (const line of lines) {
const [domain, a, b, hash] = line.split(" ");
expect(await poseidon["poseidon(uint256[2],uint256)"]([a, b], domain)).to.eq(toBigInt(hash));
}
});
});
});

View File

@@ -1,149 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { ZeroAddress } from "ethers";
import { ethers } from "hardhat";
import { ScrollChain, L1MessageQueue } from "../typechain";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { randomBytes } from "crypto";
import { expect } from "chai";
describe("ScrollChain.blob", async () => {
let deployer: HardhatEthersSigner;
let signer: HardhatEthersSigner;
let queue: L1MessageQueue;
let chain: ScrollChain;
beforeEach(async () => {
[deployer, signer] = await ethers.getSigners();
const EmptyContract = await ethers.getContractFactory("EmptyContract", deployer);
const empty = await EmptyContract.deploy();
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
const admin = await ProxyAdmin.deploy();
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const queueProxy = await TransparentUpgradeableProxy.deploy(empty.getAddress(), admin.getAddress(), "0x");
const chainProxy = await TransparentUpgradeableProxy.deploy(empty.getAddress(), admin.getAddress(), "0x");
const L1MessageQueue = await ethers.getContractFactory("L1MessageQueue", deployer);
const queueImpl = await L1MessageQueue.deploy(deployer.address, chainProxy.getAddress(), deployer.address);
await admin.upgrade(queueProxy.getAddress(), queueImpl.getAddress());
const ScrollChain = await ethers.getContractFactory("ScrollChain", deployer);
const chainImpl = await ScrollChain.deploy(0, queueProxy.getAddress(), deployer.address);
await admin.upgrade(chainProxy.getAddress(), chainImpl.getAddress());
queue = await ethers.getContractAt("L1MessageQueue", await queueProxy.getAddress(), deployer);
chain = await ethers.getContractAt("ScrollChain", await chainProxy.getAddress(), deployer);
await chain.initialize(queue.getAddress(), ZeroAddress, 100);
await chain.addSequencer(deployer.address);
await chain.addProver(deployer.address);
await queue.initialize(deployer.address, chain.getAddress(), deployer.address, deployer.address, 10000000);
});
context("commit batch", async () => {
let batchHeader0: Uint8Array;
beforeEach(async () => {
// import 10 L1 messages
for (let i = 0; i < 10; i++) {
queue.appendCrossDomainMessage(deployer.address, 1000000, "0x");
}
// import genesis batch first
batchHeader0 = new Uint8Array(89);
batchHeader0[25] = 1;
await chain.importGenesisBatch(batchHeader0, randomBytes(32));
});
it("should revert when caller is not sequencer", async () => {
await expect(chain.connect(signer).commitBatch(1, batchHeader0, [], "0x")).to.revertedWithCustomError(
chain,
"ErrorCallerIsNotSequencer"
);
});
it("should revert when batch is empty", async () => {
await expect(chain.commitBatch(1, batchHeader0, [], "0x")).to.revertedWithCustomError(chain, "ErrorBatchIsEmpty");
});
it("should revert when batch header length too small", async () => {
const header = new Uint8Array(120);
header[0] = 1;
await expect(chain.commitBatch(1, header, ["0x"], "0x")).to.revertedWithCustomError(
chain,
"ErrorBatchHeaderLengthTooSmall"
);
});
it("should revert when wrong bitmap length", async () => {
const header = new Uint8Array(122);
header[0] = 1;
await expect(chain.commitBatch(1, header, ["0x"], "0x")).to.revertedWithCustomError(
chain,
"ErrorIncorrectBitmapLength"
);
});
it("should revert when incorrect parent batch hash", async () => {
batchHeader0[25] = 2;
await expect(chain.commitBatch(1, batchHeader0, ["0x"], "0x")).to.revertedWithCustomError(
chain,
"ErrorIncorrectBatchHash"
);
batchHeader0[25] = 1;
});
it("should revert when ErrorNoBlobFound", async () => {
await expect(chain.commitBatch(1, batchHeader0, ["0x"], "0x")).to.revertedWithCustomError(
chain,
"ErrorNoBlobFound"
);
});
/* Hardhat doesn't have support for EIP4844 yet.
const makeTransaction = async (data: string, value: bigint, blobVersionedHashes: Array<string>) => {
const tx = new Transaction();
tx.type = 3;
tx.to = await chain.getAddress();
tx.data = data;
tx.nonce = await deployer.getNonce();
tx.gasLimit = 1000000;
tx.maxPriorityFeePerGas = (await ethers.provider.getFeeData()).maxPriorityFeePerGas;
tx.maxFeePerGas = (await ethers.provider.getFeeData()).maxFeePerGas;
tx.value = value;
tx.chainId = (await ethers.provider.getNetwork()).chainId;
tx.maxFeePerBlobGas = ethers.parseUnits("1", "gwei");
tx.blobVersionedHashes = blobVersionedHashes;
return tx;
};
it("should revert when ErrorFoundMultipleBlob", async () => {
const data = chain.interface.encodeFunctionData("commitBatch", [1, batchHeader0, ["0x"], "0x"]);
const tx = await makeTransaction(data, 0n, [ZeroHash, ZeroHash]);
const signature = await deployer.signMessage(tx.unsignedHash);
tx.signature = Signature.from(signature);
const r = await ethers.provider.broadcastTransaction(tx.serialized);
await expect(r).to.revertedWithCustomError(chain, "ErrorFoundMultipleBlob");
});
it("should revert when ErrorNoBlockInChunk", async () => {});
it("should revert when ErrorIncorrectChunkLength", async () => {});
it("should revert when ErrorLastL1MessageSkipped", async () => {});
it("should revert when ErrorNumTxsLessThanNumL1Msgs", async () => {});
it("should revert when ErrorTooManyTxsInOneChunk", async () => {});
it("should revert when ErrorIncorrectBitmapLength", async () => {});
it("should succeed", async () => {});
*/
});
});

View File

@@ -1,92 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { ZeroAddress, concat, getBytes } from "ethers";
import { ethers } from "hardhat";
import { ScrollChain, L1MessageQueue } from "../typechain";
describe("ScrollChain", async () => {
let queue: L1MessageQueue;
let chain: ScrollChain;
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const EmptyContract = await ethers.getContractFactory("EmptyContract", deployer);
const empty = await EmptyContract.deploy();
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
const admin = await ProxyAdmin.deploy();
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const queueProxy = await TransparentUpgradeableProxy.deploy(empty.getAddress(), admin.getAddress(), "0x");
const chainProxy = await TransparentUpgradeableProxy.deploy(empty.getAddress(), admin.getAddress(), "0x");
const L1MessageQueue = await ethers.getContractFactory("L1MessageQueue", deployer);
const queueImpl = await L1MessageQueue.deploy(ZeroAddress, chainProxy.getAddress(), deployer.address);
await admin.upgrade(queueProxy.getAddress(), queueImpl.getAddress());
const ScrollChain = await ethers.getContractFactory("ScrollChain", deployer);
const chainImpl = await ScrollChain.deploy(0, queueProxy.getAddress(), deployer.address);
await admin.upgrade(chainProxy.getAddress(), chainImpl.getAddress());
queue = await ethers.getContractAt("L1MessageQueue", await queueProxy.getAddress(), deployer);
chain = await ethers.getContractAt("ScrollChain", await chainProxy.getAddress(), deployer);
await chain.initialize(queue.getAddress(), ZeroAddress, 100);
await chain.addSequencer(deployer.address);
await queue.initialize(ZeroAddress, chain.getAddress(), ZeroAddress, ZeroAddress, 10000000);
});
// @note skip this benchmark tests
it.skip("should succeed", async () => {
const batchHeader0 = new Uint8Array(89);
batchHeader0[25] = 1;
await chain.importGenesisBatch(batchHeader0, "0x0000000000000000000000000000000000000000000000000000000000000001");
const parentBatchHash = await chain.committedBatches(0);
console.log("genesis batch hash:", parentBatchHash);
console.log(`ChunkPerBatch`, `BlockPerChunk`, `TxPerBlock`, `BytesPerTx`, `TotalBytes`, `EstimateGas`);
for (let numChunks = 3; numChunks <= 6; ++numChunks) {
for (let numBlocks = 1; numBlocks <= 5; ++numBlocks) {
for (let numTx = 20; numTx <= Math.min(30, 100 / numBlocks); ++numTx) {
for (let txLength = 800; txLength <= 1000; txLength += 100) {
const txs: Array<Uint8Array> = [];
for (let i = 0; i < numTx; i++) {
const tx = new Uint8Array(4 + txLength);
let offset = 3;
for (let x = txLength; x > 0; x = Math.floor(x / 256)) {
tx[offset] = x % 256;
offset -= 1;
}
tx.fill(1, 4);
txs.push(tx);
}
const chunk = new Uint8Array(1 + 60 * numBlocks);
chunk[0] = numBlocks;
for (let i = 0; i < numBlocks; i++) {
chunk[1 + i * 60 + 57] = numTx;
}
const chunks: Array<Uint8Array> = [];
for (let i = 0; i < numChunks; i++) {
const txsInChunk: Array<Uint8Array> = [];
for (let j = 0; j < numBlocks; j++) {
txsInChunk.push(getBytes(concat(txs)));
}
chunks.push(getBytes(concat([chunk, concat(txsInChunk)])));
}
const estimateGas = await chain.commitBatch.estimateGas(0, batchHeader0, chunks, "0x");
console.log(
`${numChunks}`,
`${numBlocks}`,
`${numTx}`,
`${txLength}`,
`${numChunks * numBlocks * numTx * (txLength + 1)}`,
`${estimateGas.toString()}`
);
}
}
}
}
});
});

View File

@@ -1,45 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { hexlify } from "ethers";
import fs from "fs";
import { ethers } from "hardhat";
import { ZkEvmVerifierV1 } from "../typechain";
describe("ZkEvmVerifierV1", async () => {
let deployer: HardhatEthersSigner;
let zkEvmVerifier: ZkEvmVerifierV1;
beforeEach(async () => {
[deployer] = await ethers.getSigners();
const bytecode = hexlify(fs.readFileSync("./src/libraries/verifier/plonk-verifier/plonk_verifier_0.9.8.bin"));
const tx = await deployer.sendTransaction({ data: bytecode });
const receipt = await tx.wait();
const ZkEvmVerifierV1 = await ethers.getContractFactory("ZkEvmVerifierV1", deployer);
zkEvmVerifier = await ZkEvmVerifierV1.deploy(receipt!.contractAddress!);
});
it("should succeed", async () => {
const proof = hexlify(fs.readFileSync("./integration-test/testdata/plonk_verifier_0.9.8_proof.data"));
const instances = fs.readFileSync("./integration-test/testdata/plonk_verifier_0.9.8_pi.data");
const publicInputHash = new Uint8Array(32);
for (let i = 0; i < 32; i++) {
publicInputHash[i] = instances[i * 32 + 31];
}
expect(hexlify(publicInputHash)).to.eq("0x31b430667bc9e8a8b7eda5e5c76f2250c64023f5f8e0689ac9f4e53f5362da66");
// verify ok
await zkEvmVerifier.verify(proof, publicInputHash);
console.log("Gas Usage:", (await zkEvmVerifier.verify.estimateGas(proof, publicInputHash)).toString());
// verify failed
await expect(zkEvmVerifier.verify(proof, publicInputHash.reverse())).to.reverted;
});
});

View File

@@ -1,604 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { expect } from "chai";
import { ethers } from "hardhat";
import { generateABI, createCode } from "../scripts/poseidon";
import { MockZkTrieVerifier } from "../typechain";
import { concat } from "ethers";
const chars = "0123456789abcdef";
interface ITestConfig {
block: number;
desc: string;
account: string;
storage: string;
expectedRoot: string;
expectedValue: string;
accountProof: string[];
storageProof: string[];
}
const testcases: Array<ITestConfig> = [
{
// curl -H "content-type: application/json" -X POST --data '{"id":0,"jsonrpc":"2.0","method":"eth_getProof","params":["0x5300000000000000000000000000000000000004", ["0x8391082587ea494a8beba02cc40273f27e5477a967cd400736ac46950da0b378"], "0x1111ad"]}' https://rpc.scroll.io
block: 1118637,
desc: "WETH.balance[0xa7994f02237aed2c116a702a8f5322a1fb325b31]",
account: "0x5300000000000000000000000000000000000004",
storage: "0x8391082587ea494a8beba02cc40273f27e5477a967cd400736ac46950da0b378",
expectedRoot: "0x1334a21a74914182745c1f5142e70b487262096784ae7669186657462c01b103",
expectedValue: "0x00000000000000000000000000000000000000000000000000006239b5a2c000",
accountProof: [
"0x0907d980105678a2007eb5683d850f36a9caafe6e7fd3279987d7a94a13a360d3a1478f9a4c1f8c755227ee3544929bb0d7cfa2d999a48493d048ff0250bb002ab",
"0x092b59a024f142555555c767842c4fcc3996686c57699791fcb10013f69ffd9b2507360087cb303767fd43f2650960621246a8d205d086e03d9c1626e4aaa5b143",
"0x091f876342916ac1d5a14ef40cfc5644452170b16d1b045877f303cd52322ba1e00ba09f36443c2a63fbd7ff8feeb2c84e99fde6db08fd8e4c67ad061c482ff276",
"0x09277b3069a4b944a45df222366aae727ec64efaf0a8ecb000645d0eea3a3fa93609b925158cc04f610f8c616369094683ca7a86239f49e97852aa286d148a3913",
"0x092fb789200a7324067934da8be91c48f86c4e6f35fed6d1ce8ae4d7051f480bc0074019222c788b139b6919dfbc9d0b51f274e0ed3ea03553b8db30392ac05ce4",
"0x092f79da8f9f2c3a3a3813580ff18d4619b95f54026b2f16ccbcca684d5e25e1f52912fa319d9a7ba537a52cc6571844b4d1aa99b8a78cea6f686a6279ade5dcae",
"0x09249d249bcf92a369bd7715ec63a4b29d706a5dbb304efd678a2e5d7982e7fa9b202e3225c1031d83ab62d78516a4cbdbf2b22842c57182e7cb0dbb4303ac38c5",
"0x0904837ebb85ceccab225d4d826fe57edca4b00862199b91082f65dfffa7669b90039c710273b02e60c2e74eb8b243721e852e0e56fa51668b6362fd920f817cb7",
"0x090a36f6aabc3768a05dd8f93667a0eb2e5b63d94b5ce27132fb38d13c56d49cb4249c2013daee90184ae285226271f150f6a8f74f2c85dbd0721c5f583e620b10",
"0x091b82f139a06af573e871fdd5f5ac18f17c568ffe1c9e271505b371ad7f0603e716b187804a49d2456a0baa7c2317c14d9aa7e58ad64df38bc6c1c7b86b072333",
"0x0929668e59dfc2e2aef10194f5d287d8396e1a897d68f106bdb12b9541c0bab71d2bf910dea11e3209b3feff88d630af46006e402e935bc84c559694d88c117733",
"0x0914231c92f09f56628c10603dc2d2120d9d11b27fa23753a14171127c3a1ee3dd0d6b9cbd11d031fe6e1b650023edc58aa580fa4f4aa1b30bf82e0e4c7a308bb9",
"0x0914c1dd24c520d96aac93b7ef3062526067f1b15a080c482abf449d3c2cde781b195eb63b5e328572090319310914d81b2ca8350b6e15dc9d13e878f8c28c9d52",
"0x0927cb93e3d9c144a5a3653c5cf2ed5940d64f461dd588cd192516ae7d855e9408166e85986d4c9836cd6cd822174ba9db9c7a043d73e86b5b2cfc0a2e082894c3",
"0x090858bf8a0119626fe9339bd92116a070ba1a66423b0f7d3f4666b6851fdea01400f7f51eb22df168c41162d7f18f9d97155d87da523b05a1dde54e7a30a98c31",
"0x0902776c1f5f93a95baea2e209ddb4a5e49dd1112a7f7d755a45addffe4a233dad0d8cc62b957d9b254fdc8199c720fcf8d5c65d14899911e991b4530710aca75e",
"0x091d7fde5c78c88bbf6082a20a185cde96a203ea0d29c829c1ab9322fc3ca0ae3100ef7cba868cac216d365a0232ad6227ab1ef3290166bc6c19b719b79dbc17fc",
"0x091690160269c53c6b74337a00d02cb40a88ea5eba06e1942088b619baee83279e12d96d62dda9c4b5897d58fea40b5825d87a5526dec37361ec7c93a3256ea76d",
"0x091bccb091cde3f8ca7cfda1df379c9bfa412908c41037ae4ec0a20ce984e2c9a51d02c109d2e6e25dc60f10b1bc3b3f97ca1ce1aa025ce4f3146de3979403b99e",
"0x0927083540af95e57acba69671a4a596f721432549b8760941f4251e0dd7a013a917cee0f60d333cf88e40ae8710fb1fd6e3920346a376b3ba6686a4b2020a043e",
"0x082170b57b8f05f6990eec62e74cdb303741f6c464a85d68582c19c51e53f490000a5029a62ddc14c9c07c549db300bd308b6367454966c94b8526f4ceed5693b2",
"0x0827a0b16ef333dcfe00610d19dc468b9e856f544c9b5e9b046357e0a38aedaeb90000000000000000000000000000000000000000000000000000000000000000",
"0x06126f891e8753e67c5cbfa2a67e9d71942eab3a88cde86e97a4af94ea0dde497821fb69ccdb00e6eaeaf7fc1e73630f39f846970b72ac801e396da0033fb0c247",
"0x0420e9fb498ff9c35246d527da24aa1710d2cc9b055ecf9a95a8a2a11d3d836cdf050800000000000000000000000000000000000000000000000016ef00000000000000000000000000000000000000000000000000000000000000600058d1a5ce14104d0dedcaecaab39b6e22c2608e40af67a71908e6e97bbf4a43c59c4537140c25a9e8c4073351c26b9831c1e5af153b9be4713a4af9edfdf32b58077b735e120f14136a7980da529d9e8d3a71433fc9dc5aa8c01e3a4eb60cb3a4f9cf9ca5c8e0be205300000000000000000000000000000000000004000000000000000000000000",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
storageProof: [
"0x09240ea2601c34d792a0a5a8a84d8e501cfdfdf2c10ef13ea560acac58661882dd1b3644d1d4f3e32fc78498a7ebeffac8c6a494ac6f36923ef1be476444c0d564",
"0x0912af3ac8f8ea443e6d89d071fccaa2b3c8462220c1c2921234f613b41594f08f2a170e61f5f436b536c155b438044cf0d0f24b94b4c034ad22b3eae824998243",
"0x0916011d547d7a54929c3515078f4f672c6b390ccdd4119f0776376910bc5a38da1a059ed9c504fadcc9f77e8a402175743bee1f5be27b7002b0f6c5b51070452c",
"0x09017285edc268d979eb410b46627e541afda16cdb3577ce04c15dc14cc6609c60143f0c01e71e99b2efbe3d8e62a2c812889aa9fd88dd4b0ed8eadcf1ec9b096a",
"0x0922901e65200b007ad8e1b972e90403b336e459e0cf9b9d68732da345b1b0f6872c9e3f3edacbd857b26d0a66a80aa56c6ebaa9849e9ea5a2b17fd59cabe138e4",
"0x091b77a00164a72880eec6c18fc043fa99f922e20bbee156e1ebfd3a358bee6bbb24d97cfaa234befe197a567476cade91b7d97a1017b8d5286dae4dddadffe1cd",
"0x09216f1c4d67a9a428885bb8d978ad369d2d69d4dcc1692c3a0c3ea05da7d6f0ac2d6dda722e76eb513c67718e7be0478851758be5547322473a53b5b2b67faf95",
"0x091f56c6f18ceb7077125df1ed17a42a85956090594125c1b182161de20f8af6aa2e36977412f9ea2ad2c0951153969eca8408317558ff1b6b4ad731726235f606",
"0x092ca197dda6c519d80296f4fcda2933df9608ec684ad000133259024041d070812d29b058a998cf7ffc647b2739041725d77889f58953799c6aba6d9e5b981fc8",
"0x091c25a87d321a09ad2a149d1a7eaa77727c7feffb4c39caf44f8edd4377f7bd0c16d1091494d3c90d301c1cb4596692798e78e4cc3d53c3a08e2641de43f9da18",
"0x092166058c98245eb85b08da1c569df11f86b00cc44212a9a8ee0d60556d05a8030942c68b535651e11af38264ecc89e5f79b66c3d9ce87233ad65d4894a3d1c3d",
"0x0908c3b13b7400630170baec7448c7ec99fa9100cad373e189e42aca121e2c8f450f9e40d92d98bb0b1286a18581591fddfa8637fc941c1630237293d69e5cb98f",
"0x091362d251bbd8b255d63cd91bcfc257b8fb3ea608ce652784e3db11b22ca86c0122a0068fa1f1d54f313bed9fd9209212af3f366e4ff28092bf42c4abebffe10a",
"0x081d67961bb431a9da78eb976fabd641e20fbf4b7e32eb3faac7dfb5abb50f1faf1438d77000c1cf96c9d61347e1351eb0200260ebe523e69f6e9f334ec86e6b58",
"0x0819324d2488778bdef23319a6832001ee85f578cc920670c81f3645f898a46ec62e00385c4416ca4ccbab237b13396e5e25e5da12101021c6a6f9ecfe7c7fed19",
"0x041421380c36ea8ef65a9bdb0202b06d1e03f52857cdfea3795463653eaa3dd7d80101000000000000000000000000000000000000000000000000000000006239b5a2c000208391082587ea494a8beba02cc40273f27e5477a967cd400736ac46950da0b378",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
},
{
// curl -H "content-type: application/json" -X POST --data '{"id":0,"jsonrpc":"2.0","method":"eth_getProof","params":["0x5300000000000000000000000000000000000004", ["0x0000000000000000000000000000000000000000000000000000000000000002"], "0x1111ad"]}' https://rpc.scroll.io
block: 1118637,
desc: "WETH.totalSupply",
account: "0x5300000000000000000000000000000000000004",
storage: "0x0000000000000000000000000000000000000000000000000000000000000002",
expectedRoot: "0x1334a21a74914182745c1f5142e70b487262096784ae7669186657462c01b103",
expectedValue: "0x0000000000000000000000000000000000000000000000600058d1a5ce14104d",
accountProof: [
"0x0907d980105678a2007eb5683d850f36a9caafe6e7fd3279987d7a94a13a360d3a1478f9a4c1f8c755227ee3544929bb0d7cfa2d999a48493d048ff0250bb002ab",
"0x092b59a024f142555555c767842c4fcc3996686c57699791fcb10013f69ffd9b2507360087cb303767fd43f2650960621246a8d205d086e03d9c1626e4aaa5b143",
"0x091f876342916ac1d5a14ef40cfc5644452170b16d1b045877f303cd52322ba1e00ba09f36443c2a63fbd7ff8feeb2c84e99fde6db08fd8e4c67ad061c482ff276",
"0x09277b3069a4b944a45df222366aae727ec64efaf0a8ecb000645d0eea3a3fa93609b925158cc04f610f8c616369094683ca7a86239f49e97852aa286d148a3913",
"0x092fb789200a7324067934da8be91c48f86c4e6f35fed6d1ce8ae4d7051f480bc0074019222c788b139b6919dfbc9d0b51f274e0ed3ea03553b8db30392ac05ce4",
"0x092f79da8f9f2c3a3a3813580ff18d4619b95f54026b2f16ccbcca684d5e25e1f52912fa319d9a7ba537a52cc6571844b4d1aa99b8a78cea6f686a6279ade5dcae",
"0x09249d249bcf92a369bd7715ec63a4b29d706a5dbb304efd678a2e5d7982e7fa9b202e3225c1031d83ab62d78516a4cbdbf2b22842c57182e7cb0dbb4303ac38c5",
"0x0904837ebb85ceccab225d4d826fe57edca4b00862199b91082f65dfffa7669b90039c710273b02e60c2e74eb8b243721e852e0e56fa51668b6362fd920f817cb7",
"0x090a36f6aabc3768a05dd8f93667a0eb2e5b63d94b5ce27132fb38d13c56d49cb4249c2013daee90184ae285226271f150f6a8f74f2c85dbd0721c5f583e620b10",
"0x091b82f139a06af573e871fdd5f5ac18f17c568ffe1c9e271505b371ad7f0603e716b187804a49d2456a0baa7c2317c14d9aa7e58ad64df38bc6c1c7b86b072333",
"0x0929668e59dfc2e2aef10194f5d287d8396e1a897d68f106bdb12b9541c0bab71d2bf910dea11e3209b3feff88d630af46006e402e935bc84c559694d88c117733",
"0x0914231c92f09f56628c10603dc2d2120d9d11b27fa23753a14171127c3a1ee3dd0d6b9cbd11d031fe6e1b650023edc58aa580fa4f4aa1b30bf82e0e4c7a308bb9",
"0x0914c1dd24c520d96aac93b7ef3062526067f1b15a080c482abf449d3c2cde781b195eb63b5e328572090319310914d81b2ca8350b6e15dc9d13e878f8c28c9d52",
"0x0927cb93e3d9c144a5a3653c5cf2ed5940d64f461dd588cd192516ae7d855e9408166e85986d4c9836cd6cd822174ba9db9c7a043d73e86b5b2cfc0a2e082894c3",
"0x090858bf8a0119626fe9339bd92116a070ba1a66423b0f7d3f4666b6851fdea01400f7f51eb22df168c41162d7f18f9d97155d87da523b05a1dde54e7a30a98c31",
"0x0902776c1f5f93a95baea2e209ddb4a5e49dd1112a7f7d755a45addffe4a233dad0d8cc62b957d9b254fdc8199c720fcf8d5c65d14899911e991b4530710aca75e",
"0x091d7fde5c78c88bbf6082a20a185cde96a203ea0d29c829c1ab9322fc3ca0ae3100ef7cba868cac216d365a0232ad6227ab1ef3290166bc6c19b719b79dbc17fc",
"0x091690160269c53c6b74337a00d02cb40a88ea5eba06e1942088b619baee83279e12d96d62dda9c4b5897d58fea40b5825d87a5526dec37361ec7c93a3256ea76d",
"0x091bccb091cde3f8ca7cfda1df379c9bfa412908c41037ae4ec0a20ce984e2c9a51d02c109d2e6e25dc60f10b1bc3b3f97ca1ce1aa025ce4f3146de3979403b99e",
"0x0927083540af95e57acba69671a4a596f721432549b8760941f4251e0dd7a013a917cee0f60d333cf88e40ae8710fb1fd6e3920346a376b3ba6686a4b2020a043e",
"0x082170b57b8f05f6990eec62e74cdb303741f6c464a85d68582c19c51e53f490000a5029a62ddc14c9c07c549db300bd308b6367454966c94b8526f4ceed5693b2",
"0x0827a0b16ef333dcfe00610d19dc468b9e856f544c9b5e9b046357e0a38aedaeb90000000000000000000000000000000000000000000000000000000000000000",
"0x06126f891e8753e67c5cbfa2a67e9d71942eab3a88cde86e97a4af94ea0dde497821fb69ccdb00e6eaeaf7fc1e73630f39f846970b72ac801e396da0033fb0c247",
"0x0420e9fb498ff9c35246d527da24aa1710d2cc9b055ecf9a95a8a2a11d3d836cdf050800000000000000000000000000000000000000000000000016ef00000000000000000000000000000000000000000000000000000000000000600058d1a5ce14104d0dedcaecaab39b6e22c2608e40af67a71908e6e97bbf4a43c59c4537140c25a9e8c4073351c26b9831c1e5af153b9be4713a4af9edfdf32b58077b735e120f14136a7980da529d9e8d3a71433fc9dc5aa8c01e3a4eb60cb3a4f9cf9ca5c8e0be205300000000000000000000000000000000000004000000000000000000000000",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
storageProof: [
"0x09240ea2601c34d792a0a5a8a84d8e501cfdfdf2c10ef13ea560acac58661882dd1b3644d1d4f3e32fc78498a7ebeffac8c6a494ac6f36923ef1be476444c0d564",
"0x0912af3ac8f8ea443e6d89d071fccaa2b3c8462220c1c2921234f613b41594f08f2a170e61f5f436b536c155b438044cf0d0f24b94b4c034ad22b3eae824998243",
"0x0916011d547d7a54929c3515078f4f672c6b390ccdd4119f0776376910bc5a38da1a059ed9c504fadcc9f77e8a402175743bee1f5be27b7002b0f6c5b51070452c",
"0x092293af71b7b9315c32d08f06e291b85e3b3dbba786dd31952369f666281aa21125ab35feae70aaca9349f6af48f7dcf2dee0324e4eae03e929963e7728b633a3",
"0x090607033a4b976c1e4683298d66b88a95ed45033ff43dea0670d84a8c42d35bf12562869385c0e70f561f18be4b78e7276b837f140a45ab12ffef1ba4ad5faecb",
"0x090abc5f713c2f58583114bb5081d00cbd01789d8efbd95e471b151c71c475142f0f52ad30f8a63288eb9dd12aca2a670de08c03f8384f55d730c943e1c472625b",
"0x0905156e8704d6195f6ae562aed2072f4e32422c6dfd4840ca354b9c4d2de5ce760fca52b1e0689ad374bae9fbea262a929f919695149a083fe6bacb806dc02fca",
"0x0917078d4c193a3fdbfe8ce3a235a0e1df89e626b5e91636097e299883fc2447892ad46eefbb27909544fe02c05e29760315749f6ce21c17c52158f5f5616c2dad",
"0x0917d02e5da8bdb969149c9327b247a6aaa479bcda4a03665da5103c10e616d2f40ccabdacdd25b34235d26e50e7af5d8d312a2cafdcadd41cc589a71a322f254c",
"0x090c62f5c476c1def8ed8a8c25ae54581690b39dfab4b0f3f78b93df96f626714328ea922a76a058087563bb5370664e9a1cebe3062f2d904bf5e3a018219d6563",
"0x091e481971f770e587b1f62f1da9ac4687abc5b2a23097fc38332e15ab957ca0ab0ec0a95c15313887e0d2f166c100deaf17f2ce50767680e6e5b2e3068801c0cd",
"0x0911799e186f1bd299dfa08c07404b9d28e2b179fb6ad523f1846872537b6db85f198b573ac1397048258de38b391fcc5e0c86a0f81f4ca607785fb37041ab8b4d",
"0x092053a028cf3bfcdabcb58985efc39f078cb0bcae4439528a0b6fe4b24bbdbd2c019a04a54e9e96077f3c2c39c1602a83387018b6357ea4c28e96764865d1c8f3",
"0x07303fad3e4628ccae4de1adb41996c9f38b22445b6525ff163b4c68cbde275b1a06111cae9b4d17b730d94f589e20c6ae2cb59bf0b40ad05bf58703ee6d46eac4",
"0x0606bc3fca1f1b3c877aa01a765c18db8b0d7f0bc50bd99f21223055bf1595c84d04fdc0fd416d8402fde743d908d032a20af6f2e65cdc6cc289f72c04f1c2476f",
"0x04020953ad52de135367a1ba2629636216ed5174cce5629d11b5d97fe733f07dcc010100000000000000000000000000000000000000000000000000600058d1a5ce14104d200000000000000000000000000000000000000000000000000000000000000002",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
},
{
// curl -H "content-type: application/json" -X POST --data '{"id":0,"jsonrpc":"2.0","method":"eth_getProof","params":["0x5300000000000000000000000000000000000004", ["0x0000000000000000000000000000000000000000000000000000000000002222"], "0x1111ad"]}' https://rpc.scroll.io
block: 1118637,
desc: "random empty storage in WETH",
account: "0x5300000000000000000000000000000000000004",
storage: "0x0000000000000000000000000000000000000000000000000000000000002222",
expectedRoot: "0x1334a21a74914182745c1f5142e70b487262096784ae7669186657462c01b103",
expectedValue: "0x0000000000000000000000000000000000000000000000000000000000000000",
accountProof: [
"0x0907d980105678a2007eb5683d850f36a9caafe6e7fd3279987d7a94a13a360d3a1478f9a4c1f8c755227ee3544929bb0d7cfa2d999a48493d048ff0250bb002ab",
"0x092b59a024f142555555c767842c4fcc3996686c57699791fcb10013f69ffd9b2507360087cb303767fd43f2650960621246a8d205d086e03d9c1626e4aaa5b143",
"0x091f876342916ac1d5a14ef40cfc5644452170b16d1b045877f303cd52322ba1e00ba09f36443c2a63fbd7ff8feeb2c84e99fde6db08fd8e4c67ad061c482ff276",
"0x09277b3069a4b944a45df222366aae727ec64efaf0a8ecb000645d0eea3a3fa93609b925158cc04f610f8c616369094683ca7a86239f49e97852aa286d148a3913",
"0x092fb789200a7324067934da8be91c48f86c4e6f35fed6d1ce8ae4d7051f480bc0074019222c788b139b6919dfbc9d0b51f274e0ed3ea03553b8db30392ac05ce4",
"0x092f79da8f9f2c3a3a3813580ff18d4619b95f54026b2f16ccbcca684d5e25e1f52912fa319d9a7ba537a52cc6571844b4d1aa99b8a78cea6f686a6279ade5dcae",
"0x09249d249bcf92a369bd7715ec63a4b29d706a5dbb304efd678a2e5d7982e7fa9b202e3225c1031d83ab62d78516a4cbdbf2b22842c57182e7cb0dbb4303ac38c5",
"0x0904837ebb85ceccab225d4d826fe57edca4b00862199b91082f65dfffa7669b90039c710273b02e60c2e74eb8b243721e852e0e56fa51668b6362fd920f817cb7",
"0x090a36f6aabc3768a05dd8f93667a0eb2e5b63d94b5ce27132fb38d13c56d49cb4249c2013daee90184ae285226271f150f6a8f74f2c85dbd0721c5f583e620b10",
"0x091b82f139a06af573e871fdd5f5ac18f17c568ffe1c9e271505b371ad7f0603e716b187804a49d2456a0baa7c2317c14d9aa7e58ad64df38bc6c1c7b86b072333",
"0x0929668e59dfc2e2aef10194f5d287d8396e1a897d68f106bdb12b9541c0bab71d2bf910dea11e3209b3feff88d630af46006e402e935bc84c559694d88c117733",
"0x0914231c92f09f56628c10603dc2d2120d9d11b27fa23753a14171127c3a1ee3dd0d6b9cbd11d031fe6e1b650023edc58aa580fa4f4aa1b30bf82e0e4c7a308bb9",
"0x0914c1dd24c520d96aac93b7ef3062526067f1b15a080c482abf449d3c2cde781b195eb63b5e328572090319310914d81b2ca8350b6e15dc9d13e878f8c28c9d52",
"0x0927cb93e3d9c144a5a3653c5cf2ed5940d64f461dd588cd192516ae7d855e9408166e85986d4c9836cd6cd822174ba9db9c7a043d73e86b5b2cfc0a2e082894c3",
"0x090858bf8a0119626fe9339bd92116a070ba1a66423b0f7d3f4666b6851fdea01400f7f51eb22df168c41162d7f18f9d97155d87da523b05a1dde54e7a30a98c31",
"0x0902776c1f5f93a95baea2e209ddb4a5e49dd1112a7f7d755a45addffe4a233dad0d8cc62b957d9b254fdc8199c720fcf8d5c65d14899911e991b4530710aca75e",
"0x091d7fde5c78c88bbf6082a20a185cde96a203ea0d29c829c1ab9322fc3ca0ae3100ef7cba868cac216d365a0232ad6227ab1ef3290166bc6c19b719b79dbc17fc",
"0x091690160269c53c6b74337a00d02cb40a88ea5eba06e1942088b619baee83279e12d96d62dda9c4b5897d58fea40b5825d87a5526dec37361ec7c93a3256ea76d",
"0x091bccb091cde3f8ca7cfda1df379c9bfa412908c41037ae4ec0a20ce984e2c9a51d02c109d2e6e25dc60f10b1bc3b3f97ca1ce1aa025ce4f3146de3979403b99e",
"0x0927083540af95e57acba69671a4a596f721432549b8760941f4251e0dd7a013a917cee0f60d333cf88e40ae8710fb1fd6e3920346a376b3ba6686a4b2020a043e",
"0x082170b57b8f05f6990eec62e74cdb303741f6c464a85d68582c19c51e53f490000a5029a62ddc14c9c07c549db300bd308b6367454966c94b8526f4ceed5693b2",
"0x0827a0b16ef333dcfe00610d19dc468b9e856f544c9b5e9b046357e0a38aedaeb90000000000000000000000000000000000000000000000000000000000000000",
"0x06126f891e8753e67c5cbfa2a67e9d71942eab3a88cde86e97a4af94ea0dde497821fb69ccdb00e6eaeaf7fc1e73630f39f846970b72ac801e396da0033fb0c247",
"0x0420e9fb498ff9c35246d527da24aa1710d2cc9b055ecf9a95a8a2a11d3d836cdf050800000000000000000000000000000000000000000000000016ef00000000000000000000000000000000000000000000000000000000000000600058d1a5ce14104d0dedcaecaab39b6e22c2608e40af67a71908e6e97bbf4a43c59c4537140c25a9e8c4073351c26b9831c1e5af153b9be4713a4af9edfdf32b58077b735e120f14136a7980da529d9e8d3a71433fc9dc5aa8c01e3a4eb60cb3a4f9cf9ca5c8e0be205300000000000000000000000000000000000004000000000000000000000000",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
storageProof: [
"0x09240ea2601c34d792a0a5a8a84d8e501cfdfdf2c10ef13ea560acac58661882dd1b3644d1d4f3e32fc78498a7ebeffac8c6a494ac6f36923ef1be476444c0d564",
"0x092fa31ba6c9b8f291512a582ab446daf7aa3787e68f9628d08ec0db329027d9001af83d361b481ed4b943d988cb0191c350b8efc85cfceba74afb60783488d441",
"0x092c2ec2d967208cb5088400d826b52113d606435be011b6c9f721f293fb12242515681c9016eb1c222dcdbeeeb9fd3a504caba892f4c1832741a2b17a7305598a",
"0x090c7fe825c29bf5df80c7101ff8a372ba4f7b2ac37c16a3bbda38cc1e38e682460499b7e5d21d3784f496e747140f465eb1a39a019d2be8baf13a5e39f359a4ed",
"0x092bb11ebbc7cd1e565b86498aecab16842ab3fa852c7943cfbc49ee4bc593b2f308a78e1bc555e07d36d5c812af57c18f67199197a52ff74bc4e32ca6b7fadf32",
"0x092fd1e042080801034c6d6c79d462016c74b97dfbb1272cf606e638911a08f21c02434541eeed6d66002c69042f9354211e40518316a2d98cc0da0f19fb1ea013",
"0x09024bd491ec707bc3e8bea6b2754f37b1e85903061aefabd945537eef2f4d38b4136b925b004d29603c5e6195e073322d27f0c6ea3fa1ea5c5b248ff60dda594c",
"0x09269e1f468bd9bbde77a13562645a80a77d26d801781ca95d385bd59ee1b0890b03694bf9043190620265bf0bc3baa4d82cc82302ae0bbf33cfa48b0ec9d5ab25",
"0x0924d8bf62b2a725684847208dc021d5aee9f3c8f14c14786bc9f93232dfd3e068120bb7d022bbb159b4b84bb9e36cd2fcd89d761e265c1b88c8bdb9745a51cb22",
"0x092680f932920fd86de0b417cfdbeb2836a470213097ed5abb1a2b4deba8437f6825fd0ec614b97e6cfa4d50b08ad1e0fd8a5cd72db3a468128d1045d6a54e5e6e",
"0x0909e630914cee4db538057a0218a72288b88b2603aee0f805254b865a03de87c92ce46c1aa77ee8c42bb60c4175826f4dbb89d6282c01ff3de654c961599e66c3",
"0x091a17302d53ad1b7a4472d111fd27b35720d49ce27259b5e42f46339dddf235e82b973c29f44cf69b589f724d7d2fa54bf38b37bde3fc66c0d965a8c10df80caa",
"0x0916572156ae22ae2b0bc84ff41d16668be7163da26db2b13b86c218e0516c97a4131b584b7192464dde26060f66f678b03c8db8f64f1cd7a1f98a22a90cce5850",
"0x092c6ee2ca598c123445bbbd403ca3ab8a95ce2443f941ebdcf7bb035e2a3e38e22e8d5b222a1019b126f0ecf277c7fed881413e879cd4dc5df66634b6e9fb688d",
"0x0700000000000000000000000000000000000000000000000000000000000000002822301c27c0bd26a8f361545a09d509a2feed981accf780de30244f0300321d",
"0x05",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
},
{
// curl -H "content-type: application/json" -X POST --data '{"id":0,"jsonrpc":"2.0","method":"eth_getProof","params":["0x5300000000000000000000000000000000000044", ["0x0000000000000000000000000000000000000000000000000000000000000000"], "0x1111ad"]}' https://rpc.scroll.io
block: 1154766,
desc: "random empty storage in some contract",
account: "0x226D078166C78e00ce5E97d8f18CDc408512bb0F",
storage: "0x0000000000000000000000000000000000000000000000000000000000000001",
expectedRoot: "0x1e5cf13822e052084c315e944ca84f1ef375583e85e1508055123a182e415fab",
expectedValue: "0x0000000000000000000000000000000000000000000000000000000000000000",
accountProof: [
"0x09062c633f6d7c7a157025fef8ab1c313a7caadda3a64b23664741f9de3b0478fe27571cf9b45d5f4deddf5f0b5354a613998fdcbe9249bb7cde92fd45513c5a99",
"0x0920d6877efe14060018278754e91682430401880981fec1cd1b63610bed0c1e332a63aca7a8898b01983e2c53a7257310318da444fd6c8b705e488943205301a8",
"0x090f6dadd53bbc0f5fa4fa03961aff0bf252ae335e11c1836253b6bc214d66759010b10d80991219a66f1eb7e07169b4cec4fa74b04edbdc08c3f238dfdf1d2fac",
"0x0921ea10af71b5f3587ff9d42178a151427cbcde37b8bee6575463bf6b83110cca0520d5f97b44e7015453ec16d9c28980d2cec3df5c860eb8a455f49dcfa339be",
"0x092d19cf96a7c129aac6f72f780703a9ef3233fc5124d592baee751a3550dd692a02c962b87efbba5aeea4856c3df29c1ea540e1fbc7a74529d5dc793fe8e490d8",
"0x0922e20a087e600560007189ccc1a159e4fffeb1876a6de3772b7f450793a1c6620ada74791f3ecd25a650701578ef9661c64e75d836c681503e96228974a53903",
"0x0924839671b636ebb56cb9a2860a3edf2a2875774e84dfcf8546135189f808d724260ac8be541ff088a9a1d2468c4c6e2faa793009be553a3cbca003649ee511db",
"0x090cd8140d844f62e44ffe820c1b2b0d4aa8f0518c15ff61759d93d805cb017cb628d5b46a4c4ec0a10eb00155808890925050f7af2279b512c25005d963283262",
"0x0913c0698673b0be011485eba05c61ac41bf14fc960ce5dbb6f5a021809eabbb0e18adaf85a3724e1a644268b845f5014b39e574928b9a01bfcd25d6fe1cf03e8f",
"0x0912c2e7da4b091c52e0012e5c13baf07d9d9daed10a558262d2e700a7c823300e054dce1849561bbeede4368a3be06f5a2bae06bdb1bc2bcefdba84634fd1991c",
"0x090b3e9c665497a0f9c1d3f1448c6d9144a287eb0accf86fea6f443f51986df7130392814f078a19643081787478ec3a010e2757a574877a194136c529813cf7ae",
"0x09249a0e273abe79a0b99a55516e19213191b7f77ef34f8815edc4e1ede8711f7920615adbac1983d844c8a6ed50922562432c13d030069d8b3e92611b4fe39531",
"0x09199575893e55d92fafb3b067130b9b6b5a46e7f6fb2d0af412d12591632dfe961adffb9dd1e7490095aac94bc1fcaeb591f4ba907fe2b882c9f6d8f7ab3a1809",
"0x09259308e9398f029ebbe31a4b353f474622b4c96995b7365c3b13c392fcc3e7001be60286a497a3886aa9cff3ad6a5dc71504078eb7a44c43530b7b33eef4743f",
"0x090709a21aaf18a1eaea3b925ab36f47a82095aa3e9ddbc4f01463005c4b64f6af0554d854637fcbfd9b1a4c2474de343950569e4f855d66f2ee14fcfb19ee17f5",
"0x092d7319be75a70b8ea5f0acc6ab4a96971ec546f72b18bdc3e905ad6ea8a288f70626499aee389335559b1dd3cc8b6711f9fde0c517236190cba24fa87993877a",
"0x09081b165a51e3081fc2e3e27d6fdb81134b65284851798de62899db3065a8c1fc040c8dce92508a510c2c34fc2949910dd41247c9f247cd216c03d9bb9d2881b4",
"0x092a27c5be32e1ab6e85d1ac094bc1509d92285f45c63fca6dba9b14d485a94af326d44c1ff85666a4790182ddd7e51cbbe06af81d62082e6d79faec29a4501369",
"0x091a46df6ffd6b439ffcd1b57e9548f5c4db26ade9e984efc8a91a01ab22134d3c1617b504ac2015793c5dac16d379b5ca6cb70c14243491bb68535ee686a3a553",
"0x08180e90f9f9a4fd8065a5849539793bd9e9340b69770eff1716a733241e454c341641f913f1c32e2c652b876f902e5c2c8d51c482411ec44dae969bdc50264c42",
"0x06273c162ecb059cd86ec0a01033dd61c39f59ee0a13eb41a28c0b2d49a45f6f94081be344adea9f54587a832b9efef6fc9ec010d86ec5fb2b53b5ff8dbabc4924",
"0x040b792f5b15327fc37390341af919c991641846d380397e4c73cbb1298921a546050800000000000000000000000000000000000000000000000000fb0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be74cc05824041ef286fd08582cdfacec7784a35af72f937acf64ade5073da10889249d61c3649abf8749bf686a73f708d67726fada3e071b03d4541da9156b20226d078166c78e00ce5e97d8f18cdc408512bb0f000000000000000000000000",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
storageProof: [
"0x05",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
},
{
// curl -H "content-type: application/json" -X POST --data '{"id":0,"jsonrpc":"2.0","method":"eth_getProof","params":["0xC73BfBD94fb1FD860997D4E76D116BDE0333BeEf", ["0x0000000000000000000000000000000000000000000000000000000000000000"], "0x2a7531"]}' https://sepolia-rpc.scroll.io
block: 2782513,
desc: "contract with only one storage entry",
account: "0xC73BfBD94fb1FD860997D4E76D116BDE0333BeEf",
storage: "0x0000000000000000000000000000000000000000000000000000000000000000",
expectedRoot: "0x13c6008daf17807163a056504e562d4adf13870306814b1a3877cda5297d5ae9",
expectedValue: "0x000000000000000000000000000000000000000000000000000000000000000c",
accountProof: [
"0x09272d92cb48d19e41ef64be1da3e10026eb87d227132becb4fba0dd1451783de425f66c55ff0bec0b012e11d64aaaa6c322566d58cf45525cb05302132518f23d",
"0x0920908000907fe2260e41f8682510eee0572937459163ea1940c2eae8b2d5862e015e7c84f56f5948bfc9c242506d14f5c3c1b97bba1b262b40b108f5d7e69287",
"0x09078402c38a02e2b3dda819b761ca6448029f3dd42ae7876ac0dba0d762e3ddb818d80485f0a15f54f110aad9a98b00bdf9ccb56bbcb069552c7f6c10be1b9c15",
"0x09123243fe438606648fe3bcef5eb0165920315fb2b9316ce3ec0daac885577f190b84d9901fc150f52ed177f23ec31de4254b293c6eac2088009f3e13e3a08b78",
"0x09053c59663d3eafad212f58c4834090db4bfd0ba2b13d3108e0acade089a5da9229a75e0b30abc41d4fb252faf9f3aa8ef750b780247d83186cdc333635c25038",
"0x09163255ef0b1fdec7ec97c4e002cdeb6c963ca26d9d03ebdf78eb44dfdb57e4bd1fa9f68cc583c1e7019cc62133ede53e5636330de9a2c09e75f03760026e3729",
"0x09296d3cb1c4fd539ed015f2853649d20f5db111ce13c30b7e6efa4c9468741d1e0eea62adcf73aa5bdb4868cd776df429d26787f424beeda38f4ad19aa83e43e4",
"0x0908288df27fa423895de38ec5a52e809d99b683c5b32463501f5dad642b71387f0a3d37ae9df53b5cfdda0ac67765662e8a71a19b05d38f4a464596e129a35570",
"0x091a774fef4e8294fcca57d213846e51bfcf71249680e937e14248e532b47abd762ad72878f07f4abbba8bd13da9b75f681f35a748bb8fc078913e16a91bce783e",
"0x092799a146ba6b2bf4b6a24aef88c9590d9643d53f429438e348518a17af3d6e8d10e3b39898c3795c9386518438465581ca232445532fb549a8bddbdd6f4e0eed",
"0x0914c654d53c9f8656b784709decbd12ba786800a77c929f3b4255d59138b42dff282005f8997b73d64eeb112775885c4c08d2ee4e356cc2db58154dde48a0a1e4",
"0x091c71601a71f28ed0f6aeb59cf8a7bf29ce7dd3203352099920086e02007496260b811e85a0cd244d56f199b357d5c3a54f897fea21637698943679d07b33db8d",
"0x092a66de31cef7b4b195772a2b96edba3ca7d97a5bbe974d071c37f0d0ca0545be0be9ca0dd4c9d62ec3ba0a404713fefe6b62391ba3f6d283a47e83fdb18c3a4e",
"0x09093842042d196ae30784d31ed1526dd5d60cabe292eb5333e42936a2edbbaf1d237998efa424724063547c02cfa835ebfc24131315c34229b363f46fefda33ee",
"0x0911637da97122f89f421a4564d5328893ff4b5de123aecad06e07ea45d9622b87096a296e974b5eda0f2d35cb5531c4a55f3c1e181a8bb4a0b33399e7c93853d4",
"0x0921feeaba62a4ad78791d662737a3fa52a527dcd892f5d3af2cfbed4b6591d50f2fae639afb8ab4640a2d166616a4803442b26b9a8f5148a1c88adda1e2d911da",
"0x090ddbe424e9368f262ef80a144383fc4f518b27200f7a61a996a075b3b84ab5041c755907f230eea27d060fa827a5743c7046cd0dc7487047bc3a7d222d65d2d7",
"0x092d6e65349fd6751353b4b72fdd03d3ee4b1721efb434db76679c1c348b60fdc0177c7d961201138c98f85daf8a49b7a083a41e77dcd819d359b3db55c4a941a9",
"0x090b0d48518cb602b73a86bd7b2294d401e6ad4851e3c7549fc7d23eea017eadd72e3245236b50c7f256de16bae063df6221b8331443c9d3a79e867fd77dd85cee",
"0x07062bf32f202ec2afa65dfa84fffc76b5c05309768078544920f9b56d021606ce0b7371683425d088ad37f063ee847a9accac416314f1308cce69a8beeb2d2ab7",
"0x090ffc989b8556e69159e246cb74cf7a2e30df63e9b7dba76ede73996ab60d9799063ca19e1d436cea189d17c5d93b8da0fa11b3ee88de1030602d1e8087cbb3da",
"0x070000000000000000000000000000000000000000000000000000000000000000084f906a52b7da7bf35f3cc2431b40cfb90884c2ec0b579c9c096aea959509f7",
"0x0620b6c0072d699768c0b52df46b97dae979a14788ed54dad1d7ce67db6e036a07291784b726760c2d728e4084d95df6d1534e27284c8ae2eeb56a80210f37da2b",
"0x041245637ec55bae3c02f990e3cc3bf59cc05f515731cfa59ee55f8164953f8965050800000000000000000000000000000000000000000000000000ac000000000000000100000000000000000000000000000000000000000000000000000000000000000f68a43f5508e9c1f845406d9a507b612f97530746e59b93c8705f1a7cb0b93451e52f95aea13b1bc1f37dfbf797bfe7cea82a8c82da148f507e1ef2036fea8314b9fb07c4311e129d72b858c37b6bbe09c616f78416cb53d6e83360aff7b99c20c73bfbd94fb1fd860997d4e76d116bde0333beef000000000000000000000000",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
storageProof: [
"0x041d3c5f8c36e5da873d45bfa1d2399a572ac77493ec089cbf88a37b9e9442842201010000000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000000",
"0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449",
],
},
];
describe("ZkTrieVerifier", async () => {
let verifier: MockZkTrieVerifier;
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const PoseidonHashWithDomainFactory = new ethers.ContractFactory(generateABI(2), createCode(2), deployer);
const poseidon = await PoseidonHashWithDomainFactory.deploy();
const MockZkTrieVerifier = await ethers.getContractFactory("MockZkTrieVerifier", deployer);
verifier = await MockZkTrieVerifier.deploy(poseidon.getAddress());
});
const shouldRevert = async (test: ITestConfig, reason: string, extra?: string) => {
const proof = concat([
`0x${test.accountProof.length.toString(16).padStart(2, "0")}`,
...test.accountProof,
`0x${test.storageProof.length.toString(16).padStart(2, "0")}`,
...test.storageProof,
extra || "0x",
]);
await expect(verifier.verifyZkTrieProof(test.account, test.storage, proof)).to.revertedWith(reason);
};
for (const test of testcases) {
it(`should succeed for block[${test.block}] desc[${test.desc}] account[${test.account}] storage[${test.storage}]`, async () => {
const proof = concat([
`0x${test.accountProof.length.toString(16).padStart(2, "0")}`,
...test.accountProof,
`0x${test.storageProof.length.toString(16).padStart(2, "0")}`,
...test.storageProof,
]);
const [root, value, gasUsed] = await verifier.verifyZkTrieProof(test.account, test.storage, proof);
expect(test.expectedRoot).to.eq(root);
expect(test.expectedValue).to.eq(value);
console.log("gas usage:", gasUsed.toString());
});
}
it("should revert, when InvalidNodeDepth", async () => {
const test = testcases[0];
{
const proof = concat([
`0xfa`,
...test.accountProof,
`0x${test.storageProof.length.toString(16).padStart(2, "0")}`,
...test.storageProof,
]);
await expect(verifier.verifyZkTrieProof(test.account, test.storage, proof)).to.revertedWith("InvalidNodeDepth");
}
{
const proof = concat([
`0x${test.accountProof.length.toString(16).padStart(2, "0")}`,
...test.accountProof,
`0xfa`,
...test.storageProof,
]);
await expect(verifier.verifyZkTrieProof(test.account, test.storage, proof)).to.revertedWith("InvalidNodeDepth");
}
});
it("should revert, when InvalidBranchNodeType", async () => {
const test = testcases[0];
for (const i of [0, 1, test.accountProof.length - 3]) {
const correct = test.accountProof[i];
const prefix = correct.slice(0, 4);
for (let b = 0; b < 16; ++b) {
if (b >= 6 && b < 10) continue;
test.accountProof[i] = test.accountProof[i].replace(prefix, "0x" + chars[b >> 4] + chars[b % 16]);
await shouldRevert(test, "InvalidBranchNodeType");
test.accountProof[i] = correct;
}
}
for (const i of [0, 1, test.storageProof.length - 3]) {
const correct = test.storageProof[i];
const prefix = correct.slice(0, 4);
for (let b = 0; b < 16; ++b) {
if (b >= 6 && b < 10) continue;
test.storageProof[i] = test.storageProof[i].replace(prefix, "0x" + chars[b >> 4] + chars[b % 16]);
await shouldRevert(test, "InvalidBranchNodeType");
test.storageProof[i] = correct;
}
}
});
it("should revert, when BranchHashMismatch", async () => {
const test = testcases[0];
for (const i of [1, 2, test.accountProof.length - 3]) {
const correct = test.accountProof[i];
for (const p of [40, 98]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.accountProof[i] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "BranchHashMismatch");
test.accountProof[i] = correct;
}
}
}
for (const i of [1, 2, test.storageProof.length - 3]) {
const correct = test.storageProof[i];
for (const p of [40, 98]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.storageProof[i] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "BranchHashMismatch");
test.storageProof[i] = correct;
}
}
}
});
it("should revert, when InvalidAccountLeafNodeType", async () => {
const test = testcases[0];
const index = test.accountProof.length - 2;
const correct = test.accountProof[index];
const prefix = correct.slice(0, 4);
for (let b = 0; b < 20; ++b) {
if (b === 4 || b === 5) continue;
test.accountProof[index] = test.accountProof[index].replace(prefix, "0x" + chars[b >> 4] + chars[b % 16]);
await shouldRevert(test, "InvalidAccountLeafNodeType");
test.accountProof[index] = correct;
}
});
it("should revert, when AccountKeyMismatch", async () => {
const test = testcases[0];
const index = test.accountProof.length - 2;
const correct = test.accountProof[index];
for (const p of [4, 10]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.accountProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "AccountKeyMismatch");
test.accountProof[index] = correct;
}
}
});
it("should revert, when InvalidAccountCompressedFlag", async () => {
const test = testcases[0];
const index = test.accountProof.length - 2;
const correct = test.accountProof[index];
for (const replaced of ["01080000", "05010000"]) {
test.accountProof[index] = test.accountProof[index].replace("05080000", replaced);
await shouldRevert(test, "InvalidAccountCompressedFlag");
test.accountProof[index] = correct;
}
});
it("should revert, when InvalidAccountLeafNodeHash", async () => {
const test = testcases[0];
const index = test.accountProof.length - 2;
const correct = test.accountProof[index];
for (const p of [80, 112, 144, 176, 208]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.accountProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidAccountLeafNodeHash");
test.accountProof[index] = correct;
}
}
});
it("should revert, when InvalidAccountKeyPreimageLength", async () => {
const test = testcases[0];
const index = test.accountProof.length - 2;
const correct = test.accountProof[index];
for (const p of [396, 397]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.accountProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidAccountKeyPreimageLength");
test.accountProof[index] = correct;
}
}
});
it("should revert, when InvalidAccountKeyPreimage", async () => {
const test = testcases[0];
const index = test.accountProof.length - 2;
const correct = test.accountProof[index].slice();
for (const p of [398, 438]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.accountProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidAccountKeyPreimage");
test.accountProof[index] = correct;
}
}
});
it("should revert, when InvalidProofMagicBytes", async () => {
const test = testcases[0];
let index = test.accountProof.length - 1;
let correct = test.accountProof[index].slice();
for (const p of [2, 32, 91]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.accountProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidProofMagicBytes");
test.accountProof[index] = correct;
}
}
index = test.storageProof.length - 1;
correct = test.storageProof[index].slice();
for (const p of [2, 32, 91]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.storageProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidProofMagicBytes");
test.storageProof[index] = correct;
}
}
});
it("should revert, when InvalidAccountLeafNodeHash", async () => {
const test = testcases[0];
const correct = test.accountProof[test.accountProof.length - 2];
// change nonce
test.accountProof[test.accountProof.length - 2] = correct.replace(
"0x0420e9fb498ff9c35246d527da24aa1710d2cc9b055ecf9a95a8a2a11d3d836cdf050800000",
"0x0420e9fb498ff9c35246d527da24aa1710d2cc9b055ecf9a95a8a2a11d3d836cdf050800001"
);
await shouldRevert(test, "InvalidAccountLeafNodeHash");
test.accountProof[test.accountProof.length - 2] = correct;
});
it("should revert, when InvalidStorageLeafNodeType", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
const prefix = correct.slice(0, 4);
for (let b = 0; b < 20; ++b) {
if (b === 4 || b === 5) continue;
test.storageProof[index] = test.storageProof[index].replace(prefix, "0x" + chars[b >> 4] + chars[b % 16]);
await shouldRevert(test, "InvalidStorageLeafNodeType");
test.storageProof[index] = correct;
}
});
it("should revert, when StorageKeyMismatch", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
for (const p of [4, 10]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.storageProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "StorageKeyMismatch");
test.storageProof[index] = correct;
}
}
});
it("should revert, when InvalidStorageCompressedFlag", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
for (const replaced of ["00010000", "01000000"]) {
test.storageProof[index] = test.storageProof[index].replace("01010000", replaced);
await shouldRevert(test, "InvalidStorageCompressedFlag");
test.storageProof[index] = correct;
}
});
it("should revert, when InvalidStorageLeafNodeHash", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
for (const p of [100, 132]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.storageProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidStorageLeafNodeHash");
test.storageProof[index] = correct;
}
}
});
it("should revert, when InvalidStorageKeyPreimageLength", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
for (const p of [140, 141]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.storageProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidStorageKeyPreimageLength");
test.storageProof[index] = correct;
}
}
});
it("should revert, when InvalidStorageKeyPreimage", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
for (const p of [142, 205]) {
const v = correct[p];
for (let b = 0; b < 3; ++b) {
if (v === chars[b]) continue;
test.storageProof[index] = correct.slice(0, p) + chars[b] + correct.slice(p + 1);
await shouldRevert(test, "InvalidStorageKeyPreimage");
test.storageProof[index] = correct;
}
}
});
it("should revert, when InvalidStorageEmptyLeafNodeHash", async () => {
const test = testcases[0];
const index = test.storageProof.length - 2;
const correct = test.storageProof[index];
test.storageProof[index] = "0x05";
await shouldRevert(test, "InvalidStorageEmptyLeafNodeHash");
test.storageProof[index] = correct;
});
it("should revert, when ProofLengthMismatch", async () => {
const test = testcases[0];
await shouldRevert(test, "ProofLengthMismatch", "0x0000");
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,73 +0,0 @@
{
"name": "scroll-contracts",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"test:hardhat": "npx hardhat test",
"test:forge": "forge test -vvv --evm-version cancun",
"test": "yarn test:hardhat && yarn test:forge",
"solhint": "./node_modules/.bin/solhint -f table 'src/**/*.sol'",
"lint:sol": "./node_modules/.bin/prettier --write 'src/**/*.sol'",
"lint:ts": "./node_modules/.bin/prettier --write 'integration-test/**/*.ts' 'scripts/**/*.ts' *.ts",
"lint": "yarn lint:ts && yarn lint:sol",
"coverage": "hardhat coverage",
"coverage:forge": "forge coverage",
"prepare": "cd .. && husky install contracts/.husky"
},
"devDependencies": {
"@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
"@nomicfoundation/hardhat-ethers": "^3.0.5",
"@nomicfoundation/hardhat-verify": "^2.0.5",
"@primitivefi/hardhat-dodoc": "^0.2.3",
"@typechain/ethers-v6": "^0.5.1",
"@typechain/hardhat": "^9.1.0",
"@types/chai": "^4.2.21",
"@types/edit-json-file": "^1.7.0",
"@types/mocha": "^9.0.0",
"@types/node": "^20.11.27",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"chai": "^4.2.0",
"circom": "^0.5.46",
"circomlib": "^0.5.0",
"dotenv": "^10.0.0",
"edit-json-file": "^1.7.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-promise": "^6.1.1",
"ethereum-waffle": "^3.0.0",
"ethers": "^6.11.1",
"hardhat": "^2.22.0",
"hardhat-gas-reporter": "^1.0.4",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"lodash": "^4.17.21",
"prettier": "^2.3.2",
"prettier-plugin-solidity": "^1.0.0-beta.13",
"solhint": "^3.3.6",
"solidity-coverage": "^0.8.11",
"squirrelly": "8.0.8",
"toml": "^3.0.0",
"ts-node": "^10.1.0",
"typechain": "^8.3.2",
"typescript": "^5.4.2"
},
"dependencies": {
"@openzeppelin/contracts": "^v4.9.3",
"@openzeppelin/contracts-upgradeable": "^v4.9.3"
},
"lint-staged": {
"*.{js,ts}": "npx eslint --cache --fix",
"!(docs/apis/*).md": "prettier --ignore-unknown --write",
"*.sol": "prettier --ignore-unknown --write"
},
"engines": {
"node": ">=10.4.0"
}
}

View File

@@ -1,5 +0,0 @@
hardhat/=node_modules/hardhat/
forge-std/=lib/forge-std/src/
ds-test/=lib/ds-test/src/
solmate/=lib/solmate/src/
@openzeppelin/=node_modules/@openzeppelin

View File

@@ -1,104 +0,0 @@
# Deployment scripts of Scroll contracts
## Deployment using Hardhat
The scripts should run as below sequence:
```bash
export layer1=l1geth # change to actual network name
export layer2=l2geth # change to actual network name
export owner=0x0000000000000000000000000000000000000000 # change to actual owner
# deploy contracts in layer 1
npx hardhat --network $layer1 run scripts/deploy_proxy_admin.ts
npx hardhat --network $layer1 run scripts/deploy_scroll_chain.ts
env CONTRACT_NAME=L1ScrollMessenger npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1GatewayRouter npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1StandardERC20Gateway npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1CustomERC20Gateway npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1ERC721Gateway npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1ERC1155Gateway npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1ETHGateway npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L1WETHGateway npx hardhat run --network $layer1 scripts/deploy_proxy_contract.ts
# deploy contracts in layer 2, note: l2_messenger is predeployed
npx hardhat --network $layer2 run scripts/deploy_proxy_admin.ts
npx hardhat --network $layer2 run scripts/deploy_l2_messenger.ts
npx hardhat --network $layer2 run scripts/deploy_l2_token_factory.ts
env CONTRACT_NAME=L2GatewayRouter npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L2StandardERC20Gateway npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L2CustomERC20Gateway npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L2ERC721Gateway npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L2ERC1155Gateway npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L2ETHGateway npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
env CONTRACT_NAME=L2WETHGateway npx hardhat run --network $layer2 scripts/deploy_proxy_contract.ts
# initialize contracts in layer 1, should set proper bash env variables first
npx hardhat --network $layer1 run scripts/initialize_l1_erc20_gateway.ts
npx hardhat --network $layer1 run scripts/initialize_l1_gateway_router.ts
npx hardhat --network $layer1 run scripts/initialize_scroll_chain.ts
npx hardhat --network $layer1 run scripts/initialize_l1_messenger.ts
npx hardhat --network $layer1 run scripts/initialize_l1_custom_erc20_gateway.ts
npx hardhat --network $layer1 run scripts/initialize_l1_erc1155_gateway.ts
npx hardhat --network $layer1 run scripts/initialize_l1_erc721_gateway.ts
# initialize contracts in layer 2, should set proper bash env variables first
npx hardhat --network $layer2 run scripts/initialize_l2_erc20_gateway.ts
npx hardhat --network $layer2 run scripts/initialize_l2_gateway_router.ts
npx hardhat --network $layer2 run scripts/initialize_l2_custom_erc20_gateway.ts
npx hardhat --network $layer2 run scripts/initialize_l2_erc1155_gateway.ts
npx hardhat --network $layer2 run scripts/initialize_l2_erc721_gateway.ts
npx hardhat --network $layer2 run scripts/initialize_l2_token_factory.ts
# transfer ownership in layer 1
env CONTRACT_NAME=ProxyAdmin CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
env CONTRACT_NAME=L1ScrollMessenger CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
env CONTRACT_NAME=ZKRollup CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
env CONTRACT_NAME=L1GatewayRouter CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
env CONTRACT_NAME=L1CustomERC20Gateway CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
env CONTRACT_NAME=L1ERC721Gateway CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
env CONTRACT_NAME=L1ERC1155Gateway CONTRACT_OWNER=$owner npx hardhat run --network $layer1 scripts/transfer_ownership.ts
# transfer ownership in layer 2
env CONTRACT_NAME=ProxyAdmin CONTRACT_OWNER=$owner npx hardhat run --network $layer2 scripts/transfer_ownership.ts
env CONTRACT_NAME=L2ScrollMessenger CONTRACT_OWNER=$owner npx hardhat run --network $layer2 scripts/transfer_ownership.ts
env CONTRACT_NAME=L2GatewayRouter CONTRACT_OWNER=$owner npx hardhat run --network $layer2 scripts/transfer_ownership.ts
env CONTRACT_NAME=L2CustomERC20Gateway CONTRACT_OWNER=$owner npx hardhat run --network $layer2 scripts/transfer_ownership.ts
env CONTRACT_NAME=L2ERC721Gateway CONTRACT_OWNER=$owner npx hardhat run --network $layer2 scripts/transfer_ownership.ts
env CONTRACT_NAME=L2ERC1155Gateway CONTRACT_OWNER=$owner npx hardhat run --network $layer2 scripts/transfer_ownership.ts
```
Reference testnet [run_deploy_contracts.sh](https://github.com/scroll-tech/testnet/blob/staging/run_deploy_contracts.sh) for details.
## Deployment using Foundry
Note: The Foundry scripts take parameters like `CHAIN_ID_L2` and `L1_SCROLL_CHAIN_PROXY_ADDR` as environment variables.
```bash
# allexport
$ set -a
$ cat .env
CHAIN_ID_L2="5343541"
SCROLL_L1_RPC="http://localhost:8543"
SCROLL_L2_RPC="http://localhost:8545"
L1_DEPLOYER_PRIVATE_KEY="0x0000000000000000000000000000000000000000000000000000000000000001"
L2_DEPLOYER_PRIVATE_KEY="0x0000000000000000000000000000000000000000000000000000000000000002"
L1_ROLLUP_OPERATOR_ADDR="0x1111111111111111111111111111111111111111"
$ source .env
# Deploy L1 contracts
# Note: We extract the logged addresses as environment variables.
$ OUTPUT=$(forge script scripts/foundry/DeployL1BridgeContracts.s.sol:DeployL1BridgeContracts --rpc-url $SCROLL_L1_RPC --broadcast); echo $OUTPUT
$ echo "$OUTPUT" | grep -Eo "(L1)_.*" > .env.l1_addresses
$ source .env.l1_addresses
# Deploy L2 contracts
$ OUTPUT=$(forge script scripts/foundry/DeployL2BridgeContracts.s.sol:DeployL2BridgeContracts --rpc-url $SCROLL_L2_RPC --broadcast); echo $OUTPUT
$ echo "$OUTPUT" | grep -Eo "(L2)_.*" > .env.l2_addresses
$ source .env.l2_addresses
# Initialize contracts
$ forge script scripts/foundry/InitializeL1BridgeContracts.s.sol:InitializeL1BridgeContracts --rpc-url $SCROLL_L1_RPC --broadcast
$ forge script scripts/foundry/InitializeL2BridgeContracts.s.sol:InitializeL2BridgeContracts --rpc-url $SCROLL_L2_RPC --broadcast
```

View File

@@ -1,40 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as dotenv from "dotenv";
import { ethers } from "hardhat";
import { generateABI, createCode } from "../scripts/poseidon";
dotenv.config();
async function main() {
const [deployer] = await ethers.getSigners();
const ScrollChainCommitmentVerifier = await ethers.getContractFactory("ScrollChainCommitmentVerifier", deployer);
const L1ScrollChainAddress = process.env.L1_SCROLL_CHAIN_PROXY_ADDR!;
let PoseidonUnit2Address = process.env.POSEIDON_UNIT2_ADDR;
if (!PoseidonUnit2Address) {
const Poseidon2Elements = new ethers.ContractFactory(generateABI(2), createCode(2), deployer);
const poseidon = await Poseidon2Elements.deploy();
console.log("Deploy PoseidonUnit2 contract, hash:", poseidon.deployTransaction.hash);
const receipt = await poseidon.deployTransaction.wait();
console.log(`✅ Deploy PoseidonUnit2 contract at: ${poseidon.address}, gas used: ${receipt.gasUsed}`);
PoseidonUnit2Address = poseidon.address;
}
const verifier = await ScrollChainCommitmentVerifier.deploy(PoseidonUnit2Address, L1ScrollChainAddress, {
gasPrice: 1e9,
});
console.log("Deploy ScrollChainCommitmentVerifier contract, hash:", verifier.deployTransaction.hash);
const receipt = await verifier.deployTransaction.wait();
console.log(`✅ Deploy ScrollChainCommitmentVerifier contract at: ${verifier.address}, gas used: ${receipt.gasUsed}`);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

Some files were not shown because too many files have changed in this diff Show More