Compare commits

..

48 Commits

Author SHA1 Message Date
HAOYUatHZ
a90f2e6c4e chore: upgrade l2geth dependency for trace type (#304) 2023-02-21 10:40:46 +08:00
Xi Lin
7e99c5148d feat(contracts): new bridge contracts (#288)
Co-authored-by: Haichen Shen <shenhaichen@gmail.com>
Co-authored-by: Thegaram <th307q@gmail.com>
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2023-02-20 13:44:49 -08:00
Péter Garamvölgyi
65e0b671ff feat: import genesis batch during startup (#299)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-02-18 23:29:34 +01:00
HAOYUatHZ
3849d1bcc9 build: update version to alpha-v1.0 (#301) 2023-02-18 18:59:23 +08:00
Lawliet-Chan
f33bfffd85 feat(roller&coordinator): upgrade lizkp to zkevm-0215 version (#281)
Co-authored-by: HAOYUatHZ <haoyu@protonmail.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: xinran chen <lawliet@xinran-m1x.local>
Co-authored-by: Ubuntu <ubuntu@ip-172-31-9-248.us-west-2.compute.internal>
2023-02-18 18:53:57 +08:00
maskpp
4ad17468d0 feat(coordinator): Enable set ws compression level. (#292) 2023-02-13 19:56:30 +08:00
maskpp
fbcabcc5e2 feat(confirmations): Upgrade confirm (#291) 2023-02-12 19:06:09 +08:00
Péter Garamvölgyi
eb3f187926 feat(contracts): Add fee vault (#223) 2023-02-11 21:24:45 +01:00
Péter Garamvölgyi
d5f0218f5f feat: allow to override L2 deployment when address is provided (#293) 2023-02-10 14:28:38 +01:00
Péter Garamvölgyi
5fdd2c609c feat(bridge): confirm block based on "safe" and "finalized" tags (#265) 2023-02-09 21:20:52 +08:00
Péter Garamvölgyi
d9bc0842cc perf(bridge): execute relayer loops independently (#258)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-02-08 09:08:09 +01:00
Xi Lin
0e88b9aa94 feat(contract): enable whitelist relayer (#272)
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-02-07 14:20:34 +08:00
colin
33a912e7c1 fix(bridge): compatible with DynamicFeeTxType not supported chain (#280)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
2023-02-06 13:47:34 +08:00
HAOYUatHZ
e48e76acdf build: add nightly-2022-12-10 rust-related builder image (#282) 2023-02-06 10:33:01 +08:00
Péter Garamvölgyi
f5d02175f8 Revert "fix: add gas multiplier (#275)" (#279) 2023-02-03 11:15:45 +01:00
Lawliet-Chan
bb76a00613 feat(libzkp): use dylib instead of staticlib (#266)
Co-authored-by: maskpp <maskpp266@gmail.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
2023-02-02 15:25:50 +08:00
Péter Garamvölgyi
41d71fc274 fix: add gas multiplier (#275) 2023-02-01 19:47:53 +01:00
ChuhanJin
02ea14d721 refactor(bridge): remove layer1 client in in layer1 relayer constructor (#274)
Co-authored-by: vincent <419436363@qq.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-02-01 15:44:55 +08:00
colin
ea9c1c6776 feat: add monitor metrics (#262)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
Co-authored-by: maskpp <maskpp266@gmail.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
2023-02-01 13:46:52 +08:00
Péter Garamvölgyi
16576b6f53 fix(bridge): Handle duplicate messages (#261) 2023-01-20 12:09:47 +01:00
HAOYUatHZ
aa885f068f docs(db): fix sql comments (#260) 2023-01-20 09:44:19 +08:00
HAOYUatHZ
1f764a579d refactor(bridge): refactor layer2MessageOrm.GetL2Messages() (#243) 2023-01-20 09:29:34 +08:00
HAOYUatHZ
91ee767669 doc(db): update sql comment (#259) 2023-01-20 09:27:50 +08:00
Péter Garamvölgyi
7eac41691e feat(bridge): handle expired messages correctly (#257) 2023-01-19 23:53:34 +01:00
Péter Garamvölgyi
d9516890b0 feat(bridge): handle expired messages (#256) 2023-01-19 23:21:17 +01:00
Péter Garamvölgyi
ddb96bb732 feat(bridge): add more l1 relayer logs (#255) 2023-01-19 22:37:02 +01:00
Péter Garamvölgyi
e419dd8d5c fix(bridge): add limit to GetL1MessagesByStatus (#254) 2023-01-19 22:19:48 +01:00
Péter Garamvölgyi
c99c65bdfd fix(bridge): execute watcher loops independently (#253) 2023-01-19 21:14:45 +01:00
colin
18fd7f56a8 fix(coordinator): reset roller state when proof session timeout (#210)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-01-19 21:37:30 +08:00
Péter Garamvölgyi
a319dc1cff bugfix(bridge): only relay messages for finalized batches (#251)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
2023-01-19 20:54:09 +08:00
colin
52bf3a55fc fix(coordinator): fix CollectProofs for multi-roller & add tests (#252)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
2023-01-19 14:52:20 +08:00
Péter Garamvölgyi
598e10e4fc feat(bridge): update skipped batches in a single db operation (#242) 2023-01-18 15:21:41 +01:00
maskpp
eed3f42731 fix(coordinator): Fix bug in coordinator.GetNumberOfIdleRollers function. (#247)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
2023-01-18 20:51:19 +08:00
colin
5a4bea8ccd fix(coordinator): set session failed when all rollers have submitted invalid proof (#241)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-01-18 20:01:43 +08:00
ChuhanJin
5b37b63d89 build(jenkinsfile): replace status_check with comment in coverage test (#249)
Co-authored-by: vincent <419436363@qq.com>
2023-01-18 19:44:47 +08:00
HAOYUatHZ
5e5c4f7701 build(roller&coordinator): fix Makefile (#245)
Co-authored-by: Lawliet-Chan <1576710154@qq.com>
2023-01-18 16:51:55 +08:00
HAOYUatHZ
09dc638652 perf(db): add limit in block_batch queries (#240) 2023-01-17 20:46:51 +08:00
HAOYUatHZ
b598a01e7f build(jenkins): remove changeset condition (#239) 2023-01-17 07:07:58 +08:00
Scroll Dev
0fcdb6f824 doc: bump version number (#238) 2023-01-17 06:57:43 +08:00
Xi Lin
5a95dcf5ba bugfix(bridge&database): fix compute message hash and add unit tests (#233)
Co-authored-by: HAOYUatHZ <haoyu@protonmail.com>
2023-01-17 06:56:21 +08:00
Xi Lin
d0c63e75df bugfix(database): make sure return order of statuses in GetRollupStatusByIDList (#235)
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
2023-01-16 20:57:27 +08:00
Scroll Dev
676b8a2230 Update pull_request_template.md 2023-01-15 07:46:57 +08:00
Xi Lin
a1cb3d3b87 fix(contracts&libzkp): fix mpt circuits panic (#232)
Co-authored-by: HAOYUatHZ <haoyu@protonmail.com>
Co-authored-by: Lawliet-Chan <1576710154@qq.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-01-14 14:58:37 +08:00
colin
47b4c54e05 fix(relayer): use sync map for concurrent write (#231)
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
Co-authored-by: HAOYUatHZ <haoyu@protonmail.com>
2023-01-14 12:07:59 +08:00
maskpp
fe822a65b9 refactor(bridge): refactor bridge parallelization (#213)
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: colinlyguo <colinlyguo@gmail.com>
2023-01-14 09:40:07 +08:00
HAOYUatHZ
9bd4931f93 chore: fix typos in pull_request template (#230) 2023-01-13 11:50:39 +08:00
HAOYUatHZ
411cb19b62 chore: add pull_request template (#229) 2023-01-13 11:46:19 +08:00
HAOYUatHZ
8f55299941 Revert "refactor(coordinator): remove debug api namespace from manager" (#224)
Co-authored-by: Nazarii Denha <dengaaa2002@gmail.com>
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
2023-01-13 08:41:36 +08:00
217 changed files with 58926 additions and 14866 deletions

7
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,7 @@
1. Purpose or design rationale of this PR
2. Does this PR involve a new deployment, and involve a new git tag & docker image tag? If so, has `tag` in `common/version.go` been updated?
3. Is this PR a breaking change? If so, have it been attached a `breaking-change` label?

View File

@@ -26,7 +26,7 @@ jobs:
steps:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2022-08-23
toolchain: nightly-2022-12-10
override: true
components: rustfmt, clippy
- name: Install Go

View File

@@ -26,7 +26,7 @@ jobs:
steps:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2022-08-23
toolchain: nightly-2022-12-10
override: true
components: rustfmt, clippy
- name: Install Go

View File

@@ -26,7 +26,7 @@ jobs:
steps:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2022-08-23
toolchain: nightly-2022-12-10
override: true
components: rustfmt, clippy
- name: Install Go
@@ -42,6 +42,8 @@ jobs:
- name: Test
run: |
make roller
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./prover/lib
export CHAIN_ID=534353
go test -v ./...
check:
runs-on: ubuntu-latest

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@ assets/params*
assets/seed
coverage.txt
build/bin
*.integration.txt
# misc
sftp-config.json

40
Jenkinsfile vendored
View File

@@ -13,22 +13,12 @@ pipeline {
environment {
GO111MODULE = 'on'
PATH="/home/ubuntu/.cargo/bin:$PATH"
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./coordinator/verifier/lib"
CHAIN_ID='534353'
// LOG_DOCKER = 'true'
}
stages {
stage('Build') {
when {
anyOf {
changeset "Jenkinsfile"
changeset "build/**"
changeset "go.work**"
changeset "bridge/**"
changeset "coordinator/**"
changeset "common/**"
changeset "database/**"
changeset "tests/**"
}
}
parallel {
stage('Build Prerequisite') {
steps {
@@ -70,18 +60,6 @@ pipeline {
}
}
stage('Parallel Test') {
when {
anyOf {
changeset "Jenkinsfile"
changeset "build/**"
changeset "go.work**"
changeset "bridge/**"
changeset "coordinator/**"
changeset "common/**"
changeset "database/**"
changeset "tests/**"
}
}
parallel{
stage('Test bridge package') {
steps {
@@ -126,24 +104,12 @@ pipeline {
}
}
stage('Compare Coverage') {
when {
anyOf {
changeset "Jenkinsfile"
changeset "build/**"
changeset "go.work**"
changeset "bridge/**"
changeset "coordinator/**"
changeset "common/**"
changeset "database/**"
changeset "tests/**"
}
}
steps {
sh "./build/post-test-report-coverage.sh"
script {
currentBuild.result = 'SUCCESS'
}
step([$class: 'CompareCoverageAction', publishResultAs: 'statusCheck', scmVars: [GIT_URL: env.GIT_URL]])
step([$class: 'CompareCoverageAction', publishResultAs: 'Comment', scmVars: [GIT_URL: env.GIT_URL]])
}
}
}

View File

@@ -1,5 +1,7 @@
.PHONY: check update dev_docker clean
ZKP_VERSION=release-1220
help: ## Display this help message
@grep -h \
-E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
@@ -29,5 +31,15 @@ dev_docker: ## build docker images for development/testing usages
docker build -t scroll_l1geth ./common/docker/l1geth/
docker build -t scroll_l2geth ./common/docker/l2geth/
test_zkp: ## Test zkp prove and verify, roller/prover generates the proof and coordinator/verifier verifies it
mkdir -p test_params
wget https://circuit-release.s3.us-west-2.amazonaws.com/circuit-release/${ZKP_VERSION}/test_params/params19 -O ./test_params/params19
wget https://circuit-release.s3.us-west-2.amazonaws.com/circuit-release/${ZKP_VERSION}/test_params/params26 -O ./test_params/params26
wget https://circuit-release.s3.us-west-2.amazonaws.com/circuit-release/${ZKP_VERSION}/test_seed -O test_seed
rm -rf ./roller/assets/test_params && mv test_params ./roller/assets/ && mv test_seed ./roller/assets/
cd ./roller && make test-gpu-prover
rm -rf ./coordinator/assets/test_params && mv ./roller/assets/test_params ./coordinator/assets/ && mv ./roller/assets/agg_proof ./coordinator/assets/
cd ./coordinator && make test-gpu-verifier
clean: ## Empty out the bin folder
@rm -rf build/bin

View File

@@ -9,20 +9,20 @@ import (
)
const (
// SENT_MESSAGE_EVENT_SIGNATURE = keccak256("SentMessage(address,address,uint256,uint256,uint256,bytes,uint256,uint256)")
SENT_MESSAGE_EVENT_SIGNATURE = "806b28931bc6fbe6c146babfb83d5c2b47e971edb43b4566f010577a0ee7d9f4"
// SentMessageEventSignature = keccak256("SentMessage(address,address,uint256,uint256,uint256,bytes,uint256,uint256)")
SentMessageEventSignature = "806b28931bc6fbe6c146babfb83d5c2b47e971edb43b4566f010577a0ee7d9f4"
// RELAYED_MESSAGE_EVENT_SIGNATURE = keccak256("RelayedMessage(bytes32)")
RELAYED_MESSAGE_EVENT_SIGNATURE = "4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c"
// RelayedMessageEventSignature = keccak256("RelayedMessage(bytes32)")
RelayedMessageEventSignature = "4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c"
// FAILED_RELAYED_MESSAGE_EVENT_SIGNATURE = keccak256("FailedRelayedMessage(bytes32)")
FAILED_RELAYED_MESSAGE_EVENT_SIGNATURE = "99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f"
// FailedRelayedMessageEventSignature = keccak256("FailedRelayedMessage(bytes32)")
FailedRelayedMessageEventSignature = "99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f"
// COMMIT_BATCH_EVENT_SIGNATURE = keccak256("CommitBatch(bytes32,bytes32,uint256,bytes32)")
COMMIT_BATCH_EVENT_SIGNATURE = "a26d4bd91c4c2eff3b1bf542129607d782506fc1950acfab1472a20d28c06596"
// CommitBatchEventSignature = keccak256("CommitBatch(bytes32,bytes32,uint256,bytes32)")
CommitBatchEventSignature = "a26d4bd91c4c2eff3b1bf542129607d782506fc1950acfab1472a20d28c06596"
// FINALIZED_BATCH_EVENT_SIGNATURE = keccak256("FinalizeBatch(bytes32,bytes32,uint256,bytes32)")
FINALIZED_BATCH_EVENT_SIGNATURE = "e20f311a96205960de4d2bb351f7729e5136fa36ae64d7f736c67ddc4ca4cd4b"
// FinalizedBatchEventSignature = keccak256("FinalizeBatch(bytes32,bytes32,uint256,bytes32)")
FinalizedBatchEventSignature = "e20f311a96205960de4d2bb351f7729e5136fa36ae64d7f736c67ddc4ca4cd4b"
)
var (

View File

@@ -1,6 +1,7 @@
package app
import (
"context"
"fmt"
"os"
"os/signal"
@@ -10,6 +11,7 @@ import (
"scroll-tech/database"
"scroll-tech/common/metrics"
"scroll-tech/common/utils"
"scroll-tech/common/version"
@@ -49,7 +51,10 @@ func action(ctx *cli.Context) error {
log.Crit("failed to load config file", "config file", cfgFile, "error", err)
}
// init db connection
// Start metrics server.
metrics.Serve(context.Background(), ctx)
// Init db connection.
var ormFactory database.OrmFactory
if ormFactory, err = database.NewOrmFactory(cfg.DBConfig); err != nil {
log.Crit("failed to init db connection", "err", err)

View File

@@ -1,6 +1,6 @@
{
"l1_config": {
"confirmations": 6,
"confirmations": "0x6",
"endpoint": "https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161",
"l1_messenger_address": "0x0000000000000000000000000000000000000000",
"rollup_contract_address": "0x0000000000000000000000000000000000000000",
@@ -11,11 +11,11 @@
"endpoint": "/var/lib/jenkins/workspace/SequencerPipeline/MyPrivateNetwork/geth.ipc",
"check_pending_time": 3,
"escalate_blocks": 100,
"confirmations": 1,
"confirmations": "0x1",
"escalate_multiple_num": 11,
"escalate_multiple_den": 10,
"max_gas_price": 10000000000,
"tx_type": "AccessListTx",
"tx_type": "LegacyTx",
"min_balance": 100000000000000000000
},
"message_sender_private_keys": [
@@ -24,7 +24,7 @@
}
},
"l2_config": {
"confirmations": 1,
"confirmations": "0x1",
"endpoint": "/var/lib/jenkins/workspace/SequencerPipeline/MyPrivateNetwork/geth.ipc",
"l2_messenger_address": "0x0000000000000000000000000000000000000000",
"relayer_config": {
@@ -34,11 +34,11 @@
"endpoint": "https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161",
"check_pending_time": 10,
"escalate_blocks": 100,
"confirmations": 6,
"confirmations": "0x6",
"escalate_multiple_num": 11,
"escalate_multiple_den": 10,
"max_gas_price": 10000000000,
"tx_type": "DynamicFeeTx",
"tx_type": "LegacyTx",
"min_balance": 100000000000000000000
},
"message_sender_private_keys": [

View File

@@ -1,11 +1,14 @@
package config
import "github.com/scroll-tech/go-ethereum/common"
import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/rpc"
)
// L1Config loads l1eth configuration items.
type L1Config struct {
// Confirmations block height confirmations number.
Confirmations uint64 `json:"confirmations"`
Confirmations rpc.BlockNumber `json:"confirmations"`
// l1 eth node url.
Endpoint string `json:"endpoint"`
// The start height to sync event from layer 1

View File

@@ -3,13 +3,15 @@ package config
import (
"encoding/json"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/scroll-tech/go-ethereum/common"
)
// L2Config loads l2geth configuration items.
type L2Config struct {
// Confirmations block height confirmations number.
Confirmations uint64 `json:"confirmations"`
Confirmations rpc.BlockNumber `json:"confirmations"`
// l2geth node url.
Endpoint string `json:"endpoint"`
// The messenger contract address deployed on layer 2 chain.

View File

@@ -8,6 +8,7 @@ import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/rpc"
)
// SenderConfig The config for transaction sender
@@ -19,7 +20,7 @@ type SenderConfig struct {
// The number of blocks to wait to escalate increase gas price of the transaction.
EscalateBlocks uint64 `json:"escalate_blocks"`
// The gap number between a block be confirmed and the latest block.
Confirmations uint64 `json:"confirmations"`
Confirmations rpc.BlockNumber `json:"confirmations"`
// The numerator of gas price escalate multiple.
EscalateMultipleNum uint64 `json:"escalate_multiple_num"`
// The denominator of gas price escalate multiple.

View File

@@ -5,39 +5,37 @@ go 1.18
require (
github.com/iden3/go-iden3-crypto v0.0.13
github.com/orcaman/concurrent-map v1.0.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20221221073256-5ca70bf3a257
github.com/scroll-tech/go-ethereum v1.10.14-0.20230220082843-ec9254b0b1c6
github.com/stretchr/testify v1.8.0
github.com/urfave/cli/v2 v2.10.2
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
golang.org/x/sync v0.1.0
modernc.org/mathutil v1.4.1
)
require (
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/ethereum/go-ethereum v1.10.26 // indirect
github.com/ethereum/go-ethereum v1.11.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/holiman/uint256 v1.2.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/scroll-tech/zktrie v0.3.1 // indirect
github.com/scroll-tech/zktrie v0.5.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.4.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -73,8 +73,7 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -111,8 +110,8 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.10.13/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw=
github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum/go-ethereum v1.11.1 h1:EMymmWFzpS7G9l9NvVN8G73cgdUIqDPNRf2YTSGBXlk=
github.com/ethereum/go-ethereum v1.11.1/go.mod h1:DuefStAgaxoaYGLR0FueVcVbehmn5n9QUcVrMCuOvuc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
@@ -139,8 +138,9 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
@@ -250,8 +250,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -268,16 +267,15 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -316,7 +314,6 @@ github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHu
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -336,23 +333,22 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
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.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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.20221221073256-5ca70bf3a257 h1:FjBC0Ww42WRoiB5EQFxoIEcJqoEUw2twdhN9nGkVCQA=
github.com/scroll-tech/go-ethereum v1.10.14-0.20221221073256-5ca70bf3a257/go.mod h1:jurIpDQ0hqtp9//xxeWzr8X9KMP/+TYn+vz3K1wZrv0=
github.com/scroll-tech/zktrie v0.3.0/go.mod h1:CuJFlG1/soTJJBAySxCZgTF7oPvd5qF6utHOEciC43Q=
github.com/scroll-tech/zktrie v0.3.1 h1:HlR+fMBdjXX1/7cUMqpUgGEhGy/3vN1JpwQ0ovg/Ys8=
github.com/scroll-tech/zktrie v0.3.1/go.mod h1:CuJFlG1/soTJJBAySxCZgTF7oPvd5qF6utHOEciC43Q=
github.com/scroll-tech/go-ethereum v1.10.14-0.20230220082843-ec9254b0b1c6 h1:2kXWJR+mOj09HBh5sUTb4L/OURPSXoQd1NC/10v7otM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20230220082843-ec9254b0b1c6/go.mod h1:eW+eyNdMoO0MyuczCc9xWSnW8dPJ0kOy5xsxgOKYEaA=
github.com/scroll-tech/zktrie v0.5.0 h1:dABDR6lMZq6Hs+fWQSiHbX8s3AOX6hY+5nkhSYm5rmU=
github.com/scroll-tech/zktrie v0.5.0/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -367,8 +363,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -390,11 +386,11 @@ github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYa
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
@@ -423,8 +419,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -533,14 +529,13 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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=
@@ -552,12 +547,12 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/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.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -662,5 +657,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -26,7 +26,7 @@ func New(ctx context.Context, cfg *config.L1Config, orm database.OrmFactory) (*B
return nil, err
}
relayer, err := NewLayer1Relayer(ctx, client, int64(cfg.Confirmations), orm, cfg.RelayerConfig)
relayer, err := NewLayer1Relayer(ctx, orm, cfg.RelayerConfig)
if err != nil {
return nil, err
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/scroll-tech/go-ethereum/accounts/abi"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"scroll-tech/database/orm"
@@ -29,7 +28,6 @@ import (
// @todo It's better to be triggered by watcher.
type Layer1Relayer struct {
ctx context.Context
client *ethclient.Client
sender *sender.Sender
db orm.L1MessageOrm
@@ -43,7 +41,7 @@ type Layer1Relayer struct {
}
// NewLayer1Relayer will return a new instance of Layer1RelayerClient
func NewLayer1Relayer(ctx context.Context, ethClient *ethclient.Client, l1ConfirmNum int64, db orm.L1MessageOrm, cfg *config.RelayerConfig) (*Layer1Relayer, error) {
func NewLayer1Relayer(ctx context.Context, db orm.L1MessageOrm, cfg *config.RelayerConfig) (*Layer1Relayer, error) {
l2MessengerABI, err := bridge_abi.L2MessengerMetaData.GetAbi()
if err != nil {
log.Warn("new L2MessengerABI failed", "err", err)
@@ -59,7 +57,6 @@ func NewLayer1Relayer(ctx context.Context, ethClient *ethclient.Client, l1Confir
return &Layer1Relayer{
ctx: ctx,
client: ethClient,
sender: sender,
db: db,
l2MessengerABI: l2MessengerABI,
@@ -72,15 +69,20 @@ func NewLayer1Relayer(ctx context.Context, ethClient *ethclient.Client, l1Confir
// ProcessSavedEvents relays saved un-processed cross-domain transactions to desired blockchain
func (r *Layer1Relayer) ProcessSavedEvents() {
// msgs are sorted by nonce in increasing order
msgs, err := r.db.GetL1MessagesByStatus(orm.MsgPending)
msgs, err := r.db.GetL1MessagesByStatus(orm.MsgPending, 100)
if err != nil {
log.Error("Failed to fetch unprocessed L1 messages", "err", err)
return
}
if len(msgs) > 0 {
log.Info("Processing L1 messages", "count", len(msgs))
}
for _, msg := range msgs {
if err = r.processSavedEvent(msg); err != nil {
if !errors.Is(err, sender.ErrNoAvailableAccount) {
log.Error("failed to process event", "err", err)
log.Error("failed to process event", "msg.msgHash", msg.MsgHash, "err", err)
}
return
}
@@ -109,6 +111,12 @@ func (r *Layer1Relayer) processSavedEvent(msg *orm.L1Message) error {
}
hash, err := r.sender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), data)
if err != nil && err.Error() == "execution reverted: Message expired" {
return r.db.UpdateLayer1Status(r.ctx, msg.MsgHash, orm.MsgExpired)
}
if err != nil && err.Error() == "execution reverted: Message successfully executed" {
return r.db.UpdateLayer1Status(r.ctx, msg.MsgHash, orm.MsgConfirmed)
}
if err != nil {
return err
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"testing"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/stretchr/testify/assert"
"scroll-tech/database/migrate"
@@ -20,10 +19,7 @@ func testCreateNewL1Relayer(t *testing.T) {
assert.NoError(t, migrate.ResetDB(db.GetDB().DB))
defer db.Close()
client, err := ethclient.Dial(l1gethImg.Endpoint())
assert.NoError(t, err)
relayer, err := NewLayer1Relayer(context.Background(), client, 1, db, cfg.L2Config.RelayerConfig)
relayer, err := NewLayer1Relayer(context.Background(), db, cfg.L2Config.RelayerConfig)
assert.NoError(t, err)
defer relayer.Stop()

View File

@@ -11,6 +11,8 @@ import (
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/rpc"
"scroll-tech/database"
"scroll-tech/database/orm"
@@ -19,6 +21,10 @@ import (
"scroll-tech/bridge/utils"
)
var (
bridgeL1MsgSyncHeightGauge = metrics.NewRegisteredGauge("bridge/l1/msg/sync/height", nil)
)
type relayedMessage struct {
msgHash common.Hash
txHash common.Hash
@@ -38,7 +44,7 @@ type Watcher struct {
db database.OrmFactory
// The number of new blocks to wait for a block to be confirmed
confirmations uint64
confirmations rpc.BlockNumber
messengerAddress common.Address
messengerABI *abi.ABI
@@ -53,7 +59,7 @@ type Watcher struct {
// NewWatcher returns a new instance of Watcher. The instance will be not fully prepared,
// and still needs to be finalized and ran by calling `watcher.Start`.
func NewWatcher(ctx context.Context, client *ethclient.Client, startHeight uint64, confirmations uint64, messengerAddress common.Address, rollupAddress common.Address, db database.OrmFactory) *Watcher {
func NewWatcher(ctx context.Context, client *ethclient.Client, startHeight uint64, confirmations rpc.BlockNumber, messengerAddress common.Address, rollupAddress common.Address, db database.OrmFactory) *Watcher {
savedHeight, err := db.GetLayer1LatestWatchedHeight()
if err != nil {
log.Warn("Failed to fetch height from db", "err", err)
@@ -91,12 +97,13 @@ func (w *Watcher) Start() {
return
default:
blockNumber, err := w.client.BlockNumber(w.ctx)
number, err := utils.GetLatestConfirmedBlockNumber(w.ctx, w.client, w.confirmations)
if err != nil {
log.Error("Failed to get block number", "err", err)
log.Error("failed to get block number", "err", err)
continue
}
if err := w.FetchContractEvent(blockNumber); err != nil {
if err := w.FetchContractEvent(number); err != nil {
log.Error("Failed to fetch bridge contract", "err", err)
}
}
@@ -118,7 +125,7 @@ func (w *Watcher) FetchContractEvent(blockHeight uint64) error {
}()
fromBlock := int64(w.processedMsgHeight) + 1
toBlock := int64(blockHeight) - int64(w.confirmations)
toBlock := int64(blockHeight)
for from := fromBlock; from <= toBlock; from += contractEventsBlocksFetchLimit {
to := from + contractEventsBlocksFetchLimit - 1
@@ -138,11 +145,11 @@ func (w *Watcher) FetchContractEvent(blockHeight uint64) error {
Topics: make([][]common.Hash, 1),
}
query.Topics[0] = make([]common.Hash, 5)
query.Topics[0][0] = common.HexToHash(bridge_abi.SENT_MESSAGE_EVENT_SIGNATURE)
query.Topics[0][1] = common.HexToHash(bridge_abi.RELAYED_MESSAGE_EVENT_SIGNATURE)
query.Topics[0][2] = common.HexToHash(bridge_abi.FAILED_RELAYED_MESSAGE_EVENT_SIGNATURE)
query.Topics[0][3] = common.HexToHash(bridge_abi.COMMIT_BATCH_EVENT_SIGNATURE)
query.Topics[0][4] = common.HexToHash(bridge_abi.FINALIZED_BATCH_EVENT_SIGNATURE)
query.Topics[0][0] = common.HexToHash(bridge_abi.SentMessageEventSignature)
query.Topics[0][1] = common.HexToHash(bridge_abi.RelayedMessageEventSignature)
query.Topics[0][2] = common.HexToHash(bridge_abi.FailedRelayedMessageEventSignature)
query.Topics[0][3] = common.HexToHash(bridge_abi.CommitBatchEventSignature)
query.Topics[0][4] = common.HexToHash(bridge_abi.FinalizedBatchEventSignature)
logs, err := w.client.FilterLogs(w.ctx, query)
if err != nil {
@@ -151,6 +158,7 @@ func (w *Watcher) FetchContractEvent(blockHeight uint64) error {
}
if len(logs) == 0 {
w.processedMsgHeight = uint64(to)
bridgeL1MsgSyncHeightGauge.Update(to)
continue
}
log.Info("Received new L1 events", "fromBlock", from, "toBlock", to, "cnt", len(logs))
@@ -199,10 +207,10 @@ func (w *Watcher) FetchContractEvent(blockHeight uint64) error {
for _, msg := range relayedMessageEvents {
if msg.isSuccessful {
// succeed
err = w.db.UpdateLayer1StatusAndLayer2Hash(w.ctx, msg.msgHash.String(), orm.MsgConfirmed, msg.txHash.String())
err = w.db.UpdateLayer2StatusAndLayer1Hash(w.ctx, msg.msgHash.String(), orm.MsgConfirmed, msg.txHash.String())
} else {
// failed
err = w.db.UpdateLayer1StatusAndLayer2Hash(w.ctx, msg.msgHash.String(), orm.MsgFailed, msg.txHash.String())
err = w.db.UpdateLayer2StatusAndLayer1Hash(w.ctx, msg.msgHash.String(), orm.MsgFailed, msg.txHash.String())
}
if err != nil {
log.Error("Failed to update layer1 status and layer2 hash", "err", err)
@@ -215,6 +223,7 @@ func (w *Watcher) FetchContractEvent(blockHeight uint64) error {
}
w.processedMsgHeight = uint64(to)
bridgeL1MsgSyncHeightGauge.Update(to)
}
return nil
@@ -229,7 +238,7 @@ func (w *Watcher) parseBridgeEventLogs(logs []types.Log) ([]*orm.L1Message, []re
var rollupEvents []rollupEvent
for _, vLog := range logs {
switch vLog.Topics[0] {
case common.HexToHash(bridge_abi.SENT_MESSAGE_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.SentMessageEventSignature):
event := struct {
Target common.Address
Sender common.Address
@@ -250,7 +259,7 @@ func (w *Watcher) parseBridgeEventLogs(logs []types.Log) ([]*orm.L1Message, []re
event.Target = common.HexToAddress(vLog.Topics[1].String())
l1Messages = append(l1Messages, &orm.L1Message{
Nonce: event.MessageNonce.Uint64(),
MsgHash: utils.ComputeMessageHash(event.Target, event.Sender, event.Value, event.Fee, event.Deadline, event.Message, event.MessageNonce).String(),
MsgHash: utils.ComputeMessageHash(event.Sender, event.Target, event.Value, event.Fee, event.Deadline, event.Message, event.MessageNonce).String(),
Height: vLog.BlockNumber,
Sender: event.Sender.String(),
Value: event.Value.String(),
@@ -261,7 +270,7 @@ func (w *Watcher) parseBridgeEventLogs(logs []types.Log) ([]*orm.L1Message, []re
Calldata: common.Bytes2Hex(event.Message),
Layer1Hash: vLog.TxHash.Hex(),
})
case common.HexToHash(bridge_abi.RELAYED_MESSAGE_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.RelayedMessageEventSignature):
event := struct {
MsgHash common.Hash
}{}
@@ -272,7 +281,7 @@ func (w *Watcher) parseBridgeEventLogs(logs []types.Log) ([]*orm.L1Message, []re
txHash: vLog.TxHash,
isSuccessful: true,
})
case common.HexToHash(bridge_abi.FAILED_RELAYED_MESSAGE_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.FailedRelayedMessageEventSignature):
event := struct {
MsgHash common.Hash
}{}
@@ -283,7 +292,7 @@ func (w *Watcher) parseBridgeEventLogs(logs []types.Log) ([]*orm.L1Message, []re
txHash: vLog.TxHash,
isSuccessful: false,
})
case common.HexToHash(bridge_abi.COMMIT_BATCH_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.CommitBatchEventSignature):
event := struct {
BatchID common.Hash
BatchHash common.Hash
@@ -303,7 +312,7 @@ func (w *Watcher) parseBridgeEventLogs(logs []types.Log) ([]*orm.L1Message, []re
txHash: vLog.TxHash,
status: orm.RollupCommitted,
})
case common.HexToHash(bridge_abi.FINALIZED_BATCH_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.FinalizedBatchEventSignature):
event := struct {
BatchID common.Hash
BatchHash common.Hash

View File

@@ -27,13 +27,15 @@ func New(ctx context.Context, cfg *config.L2Config, orm database.OrmFactory) (*B
return nil, err
}
// Note: initialize watcher before relayer to keep DB consistent.
// Otherwise, there will be a race condition between watcher.initializeGenesis and relayer.ProcessPendingBatches.
l2Watcher := NewL2WatcherClient(ctx, client, cfg.Confirmations, cfg.BatchProposerConfig, cfg.L2MessengerAddress, orm)
relayer, err := NewLayer2Relayer(ctx, orm, cfg.RelayerConfig)
if err != nil {
return nil, err
}
l2Watcher := NewL2WatcherClient(ctx, client, cfg.Confirmations, cfg.BatchProposerConfig, cfg.L2MessengerAddress, orm)
return &Backend{
cfg: cfg,
l2Watcher: l2Watcher,

View File

@@ -40,7 +40,7 @@ func newBatchProposer(cfg *config.BatchProposerConfig, orm database.OrmFactory)
}
}
func (w *batchProposer) tryProposeBatch() error {
func (w *batchProposer) tryProposeBatch() {
w.mutex.Lock()
defer w.mutex.Unlock()
@@ -49,20 +49,27 @@ func (w *batchProposer) tryProposeBatch() error {
fmt.Sprintf("order by number ASC LIMIT %d", w.batchBlocksLimit),
)
if err != nil {
return err
log.Error("failed to get unbatched blocks", "err", err)
return
}
if len(blocks) == 0 {
return nil
return
}
if blocks[0].GasUsed > w.batchGasThreshold {
log.Warn("gas overflow even for only 1 block", "height", blocks[0].Number, "gas", blocks[0].GasUsed)
return w.createBatchForBlocks(blocks[:1])
if _, err = w.createBatchForBlocks(blocks[:1]); err != nil {
log.Error("failed to create batch", "number", blocks[0].Number, "err", err)
}
return
}
if blocks[0].TxNum > w.batchTxNumThreshold {
log.Warn("too many txs even for only 1 block", "height", blocks[0].Number, "tx_num", blocks[0].TxNum)
return w.createBatchForBlocks(blocks[:1])
if _, err = w.createBatchForBlocks(blocks[:1]); err != nil {
log.Error("failed to create batch", "number", blocks[0].Number, "err", err)
}
return
}
var (
@@ -83,16 +90,18 @@ func (w *batchProposer) tryProposeBatch() error {
// if it's not old enough we will skip proposing the batch,
// otherwise we will still propose a batch
if length == len(blocks) && blocks[0].BlockTimestamp+w.batchTimeSec > uint64(time.Now().Unix()) {
return nil
return
}
return w.createBatchForBlocks(blocks)
if _, err = w.createBatchForBlocks(blocks); err != nil {
log.Error("failed to create batch", "from", blocks[0].Number, "to", blocks[len(blocks)-1].Number, "err", err)
}
}
func (w *batchProposer) createBatchForBlocks(blocks []*orm.BlockInfo) error {
func (w *batchProposer) createBatchForBlocks(blocks []*orm.BlockInfo) (string, error) {
dbTx, err := w.orm.Beginx()
if err != nil {
return err
return "", err
}
var dbTxErr error
@@ -119,13 +128,13 @@ func (w *batchProposer) createBatchForBlocks(blocks []*orm.BlockInfo) error {
batchID, dbTxErr = w.orm.NewBatchInDBTx(dbTx, startBlock, endBlock, startBlock.ParentHash, txNum, gasUsed)
if dbTxErr != nil {
return dbTxErr
return "", dbTxErr
}
if dbTxErr = w.orm.SetBatchIDForBlocksInDBTx(dbTx, blockIDs, batchID); dbTxErr != nil {
return dbTxErr
return "", dbTxErr
}
dbTxErr = dbTx.Commit()
return dbTxErr
return batchID, dbTxErr
}

View File

@@ -40,7 +40,7 @@ func testBatchProposer(t *testing.T) {
// Insert traces into db.
assert.NoError(t, db.InsertBlockTraces([]*types.BlockTrace{trace2, trace3}))
id := utils.ComputeBatchID(trace3.Header.Hash(), trace2.Header.ParentHash, big.NewInt(1))
id := utils.ComputeBatchID(trace3.Header.Hash(), trace2.Header.ParentHash, big.NewInt(0))
proposer := newBatchProposer(&config.BatchProposerConfig{
ProofGenerationFreq: 1,
@@ -49,7 +49,7 @@ func testBatchProposer(t *testing.T) {
BatchTimeSec: 1,
BatchBlocksLimit: 100,
}, db)
assert.NoError(t, proposer.tryProposeBatch())
proposer.tryProposeBatch()
infos, err := db.GetUnbatchedBlocks(map[string]interface{}{},
fmt.Sprintf("order by number ASC LIMIT %d", 100))

View File

@@ -77,6 +77,7 @@ func TestFunction(t *testing.T) {
t.Run("TestL2RelayerProcessSaveEvents", testL2RelayerProcessSaveEvents)
t.Run("testL2RelayerProcessPendingBatches", testL2RelayerProcessPendingBatches)
t.Run("testL2RelayerProcessCommittedBatches", testL2RelayerProcessCommittedBatches)
t.Run("testL2RelayerSkipBatches", testL2RelayerSkipBatches)
t.Run("testBatchProposer", testBatchProposer)

View File

@@ -3,7 +3,9 @@ package l2
import (
"context"
"errors"
"fmt"
"math/big"
"runtime"
"sync"
"time"
@@ -13,6 +15,7 @@ import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/log"
"golang.org/x/sync/errgroup"
"modernc.org/mathutil"
"scroll-tech/database"
"scroll-tech/database/orm"
@@ -43,14 +46,17 @@ type Layer2Relayer struct {
rollupCh <-chan *sender.Confirmation
l1RollupABI *abi.ABI
// a list of processing message, indexed by layer2 hash
processingMessage map[string]string
// A list of processing message.
// key(string): confirmation ID, value(string): layer2 hash.
processingMessage sync.Map
// a list of processing batch commitment, indexed by batch id
processingCommitment map[string]string
// A list of processing batch commitment.
// key(string): confirmation ID, value(string): batch id.
processingCommitment sync.Map
// a list of processing batch finalization, indexed by batch id
processingFinalization map[string]string
// A list of processing batch finalization.
// key(string): confirmation ID, value(string): batch id.
processingFinalization sync.Map
stopCh chan struct{}
}
@@ -80,13 +86,15 @@ func NewLayer2Relayer(ctx context.Context, db database.OrmFactory, cfg *config.R
rollupCh: rollupSender.ConfirmChan(),
l1RollupABI: bridge_abi.RollupMetaABI,
cfg: cfg,
processingMessage: map[string]string{},
processingCommitment: map[string]string{},
processingFinalization: map[string]string{},
processingMessage: sync.Map{},
processingCommitment: sync.Map{},
processingFinalization: sync.Map{},
stopCh: make(chan struct{}),
}, nil
}
const processMsgLimit = 100
// ProcessSavedEvents relays saved un-processed cross-domain transactions to desired blockchain
func (r *Layer2Relayer) ProcessSavedEvents() {
batch, err := r.db.GetLatestFinalizedBatch()
@@ -96,7 +104,11 @@ func (r *Layer2Relayer) ProcessSavedEvents() {
}
// msgs are sorted by nonce in increasing order
msgs, err := r.db.GetL2MessagesByStatusUpToHeight(orm.MsgPending, batch.EndBlockNumber)
msgs, err := r.db.GetL2Messages(
map[string]interface{}{"status": orm.MsgPending},
fmt.Sprintf("AND height<=%d", batch.EndBlockNumber),
fmt.Sprintf("ORDER BY nonce ASC LIMIT %d", processMsgLimit),
)
if err != nil {
log.Error("Failed to fetch unprocessed L2 messages", "err", err)
@@ -104,25 +116,18 @@ func (r *Layer2Relayer) ProcessSavedEvents() {
}
// process messages in batches
batch_size := r.messageSender.NumberOfAccounts()
for from := 0; from < len(msgs); from += batch_size {
to := from + batch_size
if to > len(msgs) {
to = len(msgs)
batchSize := mathutil.Min((runtime.GOMAXPROCS(0)+1)/2, r.messageSender.NumberOfAccounts())
for size := 0; len(msgs) > 0; msgs = msgs[size:] {
if size = len(msgs); size > batchSize {
size = batchSize
}
var g errgroup.Group
for i := from; i < to; i++ {
msg := msgs[i]
for _, msg := range msgs[:size] {
msg := msg
g.Go(func() error {
return r.processSavedEvent(msg, batch)
return r.processSavedEvent(msg, batch.Index)
})
}
if err := g.Wait(); err != nil {
if !errors.Is(err, sender.ErrNoAvailableAccount) {
log.Error("failed to process l2 saved event", "err", err)
@@ -132,13 +137,13 @@ func (r *Layer2Relayer) ProcessSavedEvents() {
}
}
func (r *Layer2Relayer) processSavedEvent(msg *orm.L2Message, batch *orm.BlockBatch) error {
func (r *Layer2Relayer) processSavedEvent(msg *orm.L2Message, index uint64) error {
// @todo fetch merkle proof from l2geth
log.Info("Processing L2 Message", "msg.nonce", msg.Nonce, "msg.height", msg.Height)
proof := bridge_abi.IL1ScrollMessengerL2MessageProof{
BlockHeight: big.NewInt(int64(msg.Height)),
BatchIndex: big.NewInt(int64(batch.Index)),
BatchIndex: big.NewInt(0).SetUint64(index),
MerkleProof: make([]byte, 0),
}
from := common.HexToAddress(msg.Sender)
@@ -161,6 +166,12 @@ func (r *Layer2Relayer) processSavedEvent(msg *orm.L2Message, batch *orm.BlockBa
}
hash, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), data)
if err != nil && err.Error() == "execution reverted: Message expired" {
return r.db.UpdateLayer2Status(r.ctx, msg.MsgHash, orm.MsgExpired)
}
if err != nil && err.Error() == "execution reverted: Message successfully executed" {
return r.db.UpdateLayer2Status(r.ctx, msg.MsgHash, orm.MsgConfirmed)
}
if err != nil {
if !errors.Is(err, sender.ErrNoAvailableAccount) {
log.Error("Failed to send relayMessageWithProof tx to layer1 ", "msg.height", msg.Height, "msg.MsgHash", msg.MsgHash, "err", err)
@@ -176,14 +187,14 @@ func (r *Layer2Relayer) processSavedEvent(msg *orm.L2Message, batch *orm.BlockBa
log.Error("UpdateLayer2StatusAndLayer1Hash failed", "msgHash", msg.MsgHash, "err", err)
return err
}
r.processingMessage[msg.MsgHash] = msg.MsgHash
r.processingMessage.Store(msg.MsgHash, msg.MsgHash)
return nil
}
// ProcessPendingBatches submit batch data to layer 1 rollup contract
func (r *Layer2Relayer) ProcessPendingBatches() {
// batches are sorted by batch index in increasing order
batchesInDB, err := r.db.GetPendingBatches()
batchesInDB, err := r.db.GetPendingBatches(1)
if err != nil {
log.Error("Failed to fetch pending L2 batches", "err", err)
return
@@ -263,20 +274,28 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
}
return
}
log.Info("commitBatch in layer1", "batchID", id, "index", batch.Index, "hash", hash)
log.Info("commitBatch in layer1", "batch_id", id, "index", batch.Index, "hash", hash)
// record and sync with db, @todo handle db error
err = r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, id, hash.String(), orm.RollupCommitting)
if err != nil {
log.Error("UpdateCommitTxHashAndRollupStatus failed", "id", id, "index", batch.Index, "err", err)
}
r.processingCommitment[txID] = id
r.processingCommitment.Store(txID, id)
}
// ProcessCommittedBatches submit proof to layer 1 rollup contract
func (r *Layer2Relayer) ProcessCommittedBatches() {
// set skipped batches in a single db operation
if count, err := r.db.UpdateSkippedBatches(); err != nil {
log.Error("UpdateSkippedBatches failed", "err", err)
// continue anyway
} else if count > 0 {
log.Info("Skipping batches", "count", count)
}
// batches are sorted by batch index in increasing order
batches, err := r.db.GetCommittedBatches()
batches, err := r.db.GetCommittedBatches(1)
if err != nil {
log.Error("Failed to fetch committed L2 batches", "err", err)
return
@@ -304,6 +323,8 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
return
case orm.ProvingTaskFailed, orm.ProvingTaskSkipped:
// note: this is covered by UpdateSkippedBatches, but we keep it for completeness's sake
if err = r.db.UpdateRollupStatus(r.ctx, id, orm.RollupFinalizationSkipped); err != nil {
log.Warn("UpdateRollupStatus failed", "id", id, "err", err)
}
@@ -358,15 +379,15 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
}
return
}
log.Info("finalizeBatchWithProof in layer1", "batchID", id, "hash", hash)
log.Info("finalizeBatchWithProof in layer1", "batch_id", id, "hash", hash)
// record and sync with db, @todo handle db error
err = r.db.UpdateFinalizeTxHashAndRollupStatus(r.ctx, id, hash.String(), orm.RollupFinalizing)
if err != nil {
log.Warn("UpdateFinalizeTxHashAndRollupStatus failed", "batchID", id, "err", err)
log.Warn("UpdateFinalizeTxHashAndRollupStatus failed", "batch_id", id, "err", err)
}
success = true
r.processingFinalization[txID] = id
r.processingFinalization.Store(txID, id)
default:
log.Error("encounter unreachable case in ProcessCommittedBatches",
@@ -377,42 +398,42 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
// Start the relayer process
func (r *Layer2Relayer) Start() {
go func() {
// trigger by timer
loop := func(ctx context.Context, f func()) {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
var wg sync.WaitGroup
wg.Add(3)
go func() {
defer wg.Done()
r.ProcessSavedEvents()
}()
go func() {
defer wg.Done()
r.ProcessPendingBatches()
}()
go func() {
defer wg.Done()
r.ProcessCommittedBatches()
}()
wg.Wait()
case confirmation := <-r.messageCh:
r.handleConfirmation(confirmation)
case confirmation := <-r.rollupCh:
r.handleConfirmation(confirmation)
case <-r.stopCh:
case <-ctx.Done():
return
case <-ticker.C:
f()
}
}
}
go func() {
ctx, cancel := context.WithCancel(r.ctx)
go loop(ctx, r.ProcessSavedEvents)
go loop(ctx, r.ProcessPendingBatches)
go loop(ctx, r.ProcessCommittedBatches)
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case confirmation := <-r.messageCh:
r.handleConfirmation(confirmation)
case confirmation := <-r.rollupCh:
r.handleConfirmation(confirmation)
}
}
}(ctx)
<-r.stopCh
cancel()
}()
}
@@ -429,36 +450,36 @@ func (r *Layer2Relayer) handleConfirmation(confirmation *sender.Confirmation) {
transactionType := "Unknown"
// check whether it is message relay transaction
if msgHash, ok := r.processingMessage[confirmation.ID]; ok {
if msgHash, ok := r.processingMessage.Load(confirmation.ID); ok {
transactionType = "MessageRelay"
// @todo handle db error
err := r.db.UpdateLayer2StatusAndLayer1Hash(r.ctx, msgHash, orm.MsgConfirmed, confirmation.TxHash.String())
err := r.db.UpdateLayer2StatusAndLayer1Hash(r.ctx, msgHash.(string), orm.MsgConfirmed, confirmation.TxHash.String())
if err != nil {
log.Warn("UpdateLayer2StatusAndLayer1Hash failed", "msgHash", msgHash, "err", err)
log.Warn("UpdateLayer2StatusAndLayer1Hash failed", "msgHash", msgHash.(string), "err", err)
}
delete(r.processingMessage, confirmation.ID)
r.processingMessage.Delete(confirmation.ID)
}
// check whether it is block commitment transaction
if batch_id, ok := r.processingCommitment[confirmation.ID]; ok {
if batchID, ok := r.processingCommitment.Load(confirmation.ID); ok {
transactionType = "BatchCommitment"
// @todo handle db error
err := r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, batch_id, confirmation.TxHash.String(), orm.RollupCommitted)
err := r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, batchID.(string), confirmation.TxHash.String(), orm.RollupCommitted)
if err != nil {
log.Warn("UpdateCommitTxHashAndRollupStatus failed", "batch_id", batch_id, "err", err)
log.Warn("UpdateCommitTxHashAndRollupStatus failed", "batch_id", batchID.(string), "err", err)
}
delete(r.processingCommitment, confirmation.ID)
r.processingCommitment.Delete(confirmation.ID)
}
// check whether it is proof finalization transaction
if batch_id, ok := r.processingFinalization[confirmation.ID]; ok {
if batchID, ok := r.processingFinalization.Load(confirmation.ID); ok {
transactionType = "ProofFinalization"
// @todo handle db error
err := r.db.UpdateFinalizeTxHashAndRollupStatus(r.ctx, batch_id, confirmation.TxHash.String(), orm.RollupFinalized)
err := r.db.UpdateFinalizeTxHashAndRollupStatus(r.ctx, batchID.(string), confirmation.TxHash.String(), orm.RollupFinalized)
if err != nil {
log.Warn("UpdateFinalizeTxHashAndRollupStatus failed", "batch_id", batch_id, "err", err)
log.Warn("UpdateFinalizeTxHashAndRollupStatus failed", "batch_id", batchID.(string), "err", err)
}
delete(r.processingFinalization, confirmation.ID)
r.processingFinalization.Delete(confirmation.ID)
}
log.Info("transaction confirmed in layer1", "type", transactionType, "confirmation", confirmation)
}

View File

@@ -193,3 +193,68 @@ func testL2RelayerProcessCommittedBatches(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, orm.RollupFinalizing, status)
}
func testL2RelayerSkipBatches(t *testing.T) {
// Create db handler and reset db.
db, err := database.NewOrmFactory(cfg.DBConfig)
assert.NoError(t, err)
assert.NoError(t, migrate.ResetDB(db.GetDB().DB))
defer db.Close()
l2Cfg := cfg.L2Config
relayer, err := NewLayer2Relayer(context.Background(), db, l2Cfg.RelayerConfig)
assert.NoError(t, err)
defer relayer.Stop()
createBatch := func(rollupStatus orm.RollupStatus, provingStatus orm.ProvingStatus) string {
dbTx, err := db.Beginx()
assert.NoError(t, err)
batchID, err := db.NewBatchInDBTx(dbTx, &orm.BlockInfo{}, &orm.BlockInfo{}, "0", 1, 194676) // startBlock & endBlock & parentHash & totalTxNum & totalL2Gas don't really matter here
assert.NoError(t, err)
err = dbTx.Commit()
assert.NoError(t, err)
err = db.UpdateRollupStatus(context.Background(), batchID, rollupStatus)
assert.NoError(t, err)
tProof := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
tInstanceCommitments := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
err = db.UpdateProofByID(context.Background(), batchID, tProof, tInstanceCommitments, 100)
assert.NoError(t, err)
err = db.UpdateProvingStatus(batchID, provingStatus)
assert.NoError(t, err)
return batchID
}
skipped := []string{
createBatch(orm.RollupCommitted, orm.ProvingTaskSkipped),
createBatch(orm.RollupCommitted, orm.ProvingTaskFailed),
}
notSkipped := []string{
createBatch(orm.RollupPending, orm.ProvingTaskSkipped),
createBatch(orm.RollupCommitting, orm.ProvingTaskSkipped),
createBatch(orm.RollupFinalizing, orm.ProvingTaskSkipped),
createBatch(orm.RollupFinalized, orm.ProvingTaskSkipped),
createBatch(orm.RollupPending, orm.ProvingTaskFailed),
createBatch(orm.RollupCommitting, orm.ProvingTaskFailed),
createBatch(orm.RollupFinalizing, orm.ProvingTaskFailed),
createBatch(orm.RollupFinalized, orm.ProvingTaskFailed),
createBatch(orm.RollupCommitted, orm.ProvingTaskVerified),
}
relayer.ProcessCommittedBatches()
for _, id := range skipped {
status, err := db.GetRollupStatus(id)
assert.NoError(t, err)
assert.Equal(t, orm.RollupFinalizationSkipped, status)
}
for _, id := range notSkipped {
status, err := db.GetRollupStatus(id)
assert.NoError(t, err)
assert.NotEqual(t, orm.RollupFinalizationSkipped, status)
}
}

View File

@@ -5,7 +5,6 @@ import (
"fmt"
"math/big"
"reflect"
"sync"
"time"
geth "github.com/scroll-tech/go-ethereum"
@@ -15,6 +14,8 @@ import (
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/event"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/rpc"
bridge_abi "scroll-tech/bridge/abi"
"scroll-tech/bridge/utils"
@@ -25,6 +26,11 @@ import (
"scroll-tech/bridge/config"
)
// Metrics
var (
bridgeL2MsgSyncHeightGauge = metrics.NewRegisteredGauge("bridge/l2/msg/sync/height", nil)
)
type relayedMessage struct {
msgHash common.Hash
txHash common.Hash
@@ -40,7 +46,7 @@ type WatcherClient struct {
orm database.OrmFactory
confirmations uint64
confirmations rpc.BlockNumber
messengerAddress common.Address
messengerABI *abi.ABI
@@ -54,14 +60,14 @@ type WatcherClient struct {
}
// NewL2WatcherClient take a l2geth instance to generate a l2watcherclient instance
func NewL2WatcherClient(ctx context.Context, client *ethclient.Client, confirmations uint64, bpCfg *config.BatchProposerConfig, messengerAddress common.Address, orm database.OrmFactory) *WatcherClient {
func NewL2WatcherClient(ctx context.Context, client *ethclient.Client, confirmations rpc.BlockNumber, bpCfg *config.BatchProposerConfig, messengerAddress common.Address, orm database.OrmFactory) *WatcherClient {
savedHeight, err := orm.GetLayer2LatestWatchedHeight()
if err != nil {
log.Warn("fetch height from db failed", "err", err)
savedHeight = 0
}
return &WatcherClient{
w := WatcherClient{
ctx: ctx,
Client: client,
orm: orm,
@@ -73,6 +79,75 @@ func NewL2WatcherClient(ctx context.Context, client *ethclient.Client, confirmat
stopped: 0,
batchProposer: newBatchProposer(bpCfg, orm),
}
// Initialize genesis before we do anything else
if err := w.initializeGenesis(); err != nil {
panic(fmt.Sprintf("failed to initialize L2 genesis batch, err: %v", err))
}
return &w
}
func (w *WatcherClient) initializeGenesis() error {
if count, err := w.orm.GetBatchCount(); err != nil {
return fmt.Errorf("failed to get batch count: %v", err)
} else if count > 0 {
log.Info("genesis already imported")
return nil
}
genesis, err := w.HeaderByNumber(w.ctx, big.NewInt(0))
if err != nil {
return fmt.Errorf("failed to retrieve L2 genesis header: %v", err)
}
// EIP1559 is disabled so the RPC won't return baseFeePerGas. However, l2geth
// still uses BaseFee when calculating the block hash. If we keep it as <nil>
// here the genesis hash will not match.
genesis.BaseFee = big.NewInt(0)
log.Info("retrieved L2 genesis header", "hash", genesis.Hash().String())
trace := &types.BlockTrace{
Coinbase: nil,
Header: genesis,
Transactions: []*types.TransactionData{},
StorageTrace: nil,
ExecutionResults: []*types.ExecutionResult{},
MPTWitness: nil,
}
if err := w.orm.InsertBlockTraces([]*types.BlockTrace{trace}); err != nil {
return fmt.Errorf("failed to insert block traces: %v", err)
}
blocks, err := w.orm.GetUnbatchedBlocks(map[string]interface{}{})
if err != nil {
return err
}
if len(blocks) != 1 {
return fmt.Errorf("unexpected number of unbatched blocks in db, expected: 1, actual: %v", len(blocks))
}
batchID, err := w.batchProposer.createBatchForBlocks(blocks)
if err != nil {
return fmt.Errorf("failed to create batch: %v", err)
}
err = w.orm.UpdateProvingStatus(batchID, orm.ProvingTaskProved)
if err != nil {
return fmt.Errorf("failed to update genesis batch proving status: %v", err)
}
err = w.orm.UpdateRollupStatus(w.ctx, batchID, orm.RollupFinalized)
if err != nil {
return fmt.Errorf("failed to update genesis batch rollup status: %v", err)
}
log.Info("successfully imported genesis batch")
return nil
}
// Start the Listening process
@@ -82,56 +157,70 @@ func (w *WatcherClient) Start() {
panic("must run L2 watcher with DB")
}
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
ctx, cancel := context.WithCancel(w.ctx)
for ; true; <-ticker.C {
select {
case <-w.stopCh:
return
// trace fetcher loop
go func(ctx context.Context) {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
default:
// get current height
number, err := w.BlockNumber(w.ctx)
if err != nil {
log.Error("failed to get_BlockNumber", "err", err)
continue
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
number, err := utils.GetLatestConfirmedBlockNumber(ctx, w.Client, w.confirmations)
if err != nil {
log.Error("failed to get block number", "err", err)
continue
}
w.tryFetchRunningMissingBlocks(ctx, number)
}
if number >= w.confirmations {
number = number - w.confirmations
} else {
number = 0
}
var wg sync.WaitGroup
wg.Add(3)
go func() {
defer wg.Done()
if err := w.tryFetchRunningMissingBlocks(w.ctx, number); err != nil {
log.Error("failed to fetchRunningMissingBlocks", "err", err)
}
}()
go func() {
defer wg.Done()
// @todo handle error
if err := w.fetchContractEvent(number); err != nil {
log.Error("failed to fetchContractEvent", "err", err)
}
}()
go func() {
defer wg.Done()
if err := w.batchProposer.tryProposeBatch(); err != nil {
log.Error("failed to tryProposeBatch", "err", err)
}
}()
wg.Wait()
}
}
}(ctx)
// event fetcher loop
go func(ctx context.Context) {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
number, err := utils.GetLatestConfirmedBlockNumber(ctx, w.Client, w.confirmations)
if err != nil {
log.Error("failed to get block number", "err", err)
continue
}
w.FetchContractEvent(number)
}
}
}(ctx)
// batch proposer loop
go func(ctx context.Context) {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
w.batchProposer.tryProposeBatch()
}
}
}(ctx)
<-w.stopCh
cancel()
}()
}
@@ -143,13 +232,14 @@ func (w *WatcherClient) Stop() {
const blockTracesFetchLimit = uint64(10)
// try fetch missing blocks if inconsistent
func (w *WatcherClient) tryFetchRunningMissingBlocks(ctx context.Context, blockHeight uint64) error {
func (w *WatcherClient) tryFetchRunningMissingBlocks(ctx context.Context, blockHeight uint64) {
// Get newest block in DB. must have blocks at that time.
// Don't use "block_trace" table "trace" column's BlockTrace.Number,
// because it might be empty if the corresponding rollup_result is finalized/finalization_skipped
heightInDB, err := w.orm.GetBlockTracesLatestHeight()
if err != nil {
return fmt.Errorf("failed to GetBlockTracesLatestHeight in DB: %v", err)
log.Error("failed to GetBlockTracesLatestHeight", "err", err)
return
}
// Can't get trace from genesis block, so the default start number is 1.
@@ -167,12 +257,10 @@ func (w *WatcherClient) tryFetchRunningMissingBlocks(ctx context.Context, blockH
// Get block traces and insert into db.
if err = w.getAndStoreBlockTraces(ctx, from, to); err != nil {
log.Error("fail to getAndStoreBlockTraces", "from", from, "to", to)
return err
log.Error("fail to getAndStoreBlockTraces", "from", from, "to", to, "err", err)
return
}
}
return nil
}
func (w *WatcherClient) getAndStoreBlockTraces(ctx context.Context, from, to uint64) error {
@@ -201,7 +289,7 @@ func (w *WatcherClient) getAndStoreBlockTraces(ctx context.Context, from, to uin
const contractEventsBlocksFetchLimit = int64(10)
// FetchContractEvent pull latest event logs from given contract address and save in DB
func (w *WatcherClient) fetchContractEvent(blockHeight uint64) error {
func (w *WatcherClient) FetchContractEvent(blockHeight uint64) {
defer func() {
log.Info("l2 watcher fetchContractEvent", "w.processedMsgHeight", w.processedMsgHeight)
}()
@@ -226,17 +314,18 @@ func (w *WatcherClient) fetchContractEvent(blockHeight uint64) error {
Topics: make([][]common.Hash, 1),
}
query.Topics[0] = make([]common.Hash, 3)
query.Topics[0][0] = common.HexToHash(bridge_abi.SENT_MESSAGE_EVENT_SIGNATURE)
query.Topics[0][1] = common.HexToHash(bridge_abi.RELAYED_MESSAGE_EVENT_SIGNATURE)
query.Topics[0][2] = common.HexToHash(bridge_abi.FAILED_RELAYED_MESSAGE_EVENT_SIGNATURE)
query.Topics[0][0] = common.HexToHash(bridge_abi.SentMessageEventSignature)
query.Topics[0][1] = common.HexToHash(bridge_abi.RelayedMessageEventSignature)
query.Topics[0][2] = common.HexToHash(bridge_abi.FailedRelayedMessageEventSignature)
logs, err := w.FilterLogs(w.ctx, query)
if err != nil {
log.Error("failed to get event logs", "err", err)
return err
return
}
if len(logs) == 0 {
w.processedMsgHeight = uint64(to)
bridgeL2MsgSyncHeightGauge.Update(to)
continue
}
log.Info("received new L2 messages", "fromBlock", from, "toBlock", to, "cnt", len(logs))
@@ -244,7 +333,7 @@ func (w *WatcherClient) fetchContractEvent(blockHeight uint64) error {
sentMessageEvents, relayedMessageEvents, err := w.parseBridgeEventLogs(logs)
if err != nil {
log.Error("failed to parse emitted event log", "err", err)
return err
return
}
// Update relayed message first to make sure we don't forget to update submited message.
@@ -259,18 +348,18 @@ func (w *WatcherClient) fetchContractEvent(blockHeight uint64) error {
}
if err != nil {
log.Error("Failed to update layer1 status and layer2 hash", "err", err)
return err
return
}
}
if err = w.orm.SaveL2Messages(w.ctx, sentMessageEvents); err != nil {
return err
log.Error("failed to save l2 messages", "err", err)
return
}
w.processedMsgHeight = uint64(to)
bridgeL2MsgSyncHeightGauge.Update(to)
}
return nil
}
func (w *WatcherClient) parseBridgeEventLogs(logs []types.Log) ([]*orm.L2Message, []relayedMessage, error) {
@@ -281,7 +370,7 @@ func (w *WatcherClient) parseBridgeEventLogs(logs []types.Log) ([]*orm.L2Message
var relayedMessages []relayedMessage
for _, vLog := range logs {
switch vLog.Topics[0] {
case common.HexToHash(bridge_abi.SENT_MESSAGE_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.SentMessageEventSignature):
event := struct {
Target common.Address
Sender common.Address
@@ -302,7 +391,7 @@ func (w *WatcherClient) parseBridgeEventLogs(logs []types.Log) ([]*orm.L2Message
event.Target = common.HexToAddress(vLog.Topics[1].String())
l2Messages = append(l2Messages, &orm.L2Message{
Nonce: event.MessageNonce.Uint64(),
MsgHash: utils.ComputeMessageHash(event.Target, event.Sender, event.Value, event.Fee, event.Deadline, event.Message, event.MessageNonce).String(),
MsgHash: utils.ComputeMessageHash(event.Sender, event.Target, event.Value, event.Fee, event.Deadline, event.Message, event.MessageNonce).String(),
Height: vLog.BlockNumber,
Sender: event.Sender.String(),
Value: event.Value.String(),
@@ -313,7 +402,7 @@ func (w *WatcherClient) parseBridgeEventLogs(logs []types.Log) ([]*orm.L2Message
Calldata: common.Bytes2Hex(event.Message),
Layer2Hash: vLog.TxHash.Hex(),
})
case common.HexToHash(bridge_abi.RELAYED_MESSAGE_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.RelayedMessageEventSignature):
event := struct {
MsgHash common.Hash
}{}
@@ -324,7 +413,7 @@ func (w *WatcherClient) parseBridgeEventLogs(logs []types.Log) ([]*orm.L2Message
txHash: vLog.TxHash,
isSuccessful: true,
})
case common.HexToHash(bridge_abi.FAILED_RELAYED_MESSAGE_EVENT_SIGNATURE):
case common.HexToHash(bridge_abi.FailedRelayedMessageEventSignature):
event := struct {
MsgHash common.Hash
}{}

View File

@@ -12,6 +12,7 @@ import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/stretchr/testify/assert"
"scroll-tech/bridge/config"
@@ -36,7 +37,7 @@ func testCreateNewWatcherAndStop(t *testing.T) {
defer rc.Stop()
l1cfg := cfg.L1Config
l1cfg.RelayerConfig.SenderConfig.Confirmations = 0
l1cfg.RelayerConfig.SenderConfig.Confirmations = rpc.LatestBlockNumber
newSender, err := sender.NewSender(context.Background(), l1cfg.RelayerConfig.SenderConfig, l1cfg.RelayerConfig.MessageSenderPrivateKeys)
assert.NoError(t, err)
@@ -112,7 +113,7 @@ func testMonitorBridgeContract(t *testing.T) {
assert.NoError(t, err)
t.Log("Height in DB is", height)
assert.Greater(t, height, int64(previousHeight))
msgs, err := db.GetL2MessagesByStatus(orm.MsgPending)
msgs, err := db.GetL2Messages(map[string]interface{}{"status": orm.MsgPending})
assert.NoError(t, err)
assert.Equal(t, 2, len(msgs))
}
@@ -184,13 +185,14 @@ func testFetchMultipleSentMessageInOneBlock(t *testing.T) {
assert.NoError(t, err)
t.Log("LatestHeight is", height)
assert.Greater(t, height, int64(previousHeight)) // height must be greater than previousHeight because confirmations is 0
msgs, err := db.GetL2MessagesByStatus(orm.MsgPending)
msgs, err := db.GetL2Messages(map[string]interface{}{"status": orm.MsgPending})
assert.NoError(t, err)
assert.Equal(t, 5, len(msgs))
}
func prepareRelayerClient(l2Cli *ethclient.Client, bpCfg *config.BatchProposerConfig, db database.OrmFactory, contractAddr common.Address) *WatcherClient {
return NewL2WatcherClient(context.Background(), l2Cli, 0, bpCfg, contractAddr, db)
confirmations := rpc.LatestBlockNumber
return NewL2WatcherClient(context.Background(), l2Cli, confirmations, bpCfg, contractAddr, db)
}
func prepareAuth(t *testing.T, l2Cli *ethclient.Client, privateKey *ecdsa.PrivateKey) *bind.TransactOpts {

View File

@@ -16,10 +16,9 @@ import (
type accountPool struct {
client *ethclient.Client
minBalance *big.Int
accounts map[common.Address]*bind.TransactOpts
numAccounts int
accsCh chan *bind.TransactOpts
minBalance *big.Int
accounts map[common.Address]*bind.TransactOpts
accsCh chan *bind.TransactOpts
}
// newAccounts creates an accountPool instance.
@@ -29,11 +28,10 @@ func newAccountPool(ctx context.Context, minBalance *big.Int, client *ethclient.
minBalance.SetString("100000000000000000000", 10)
}
accs := &accountPool{
client: client,
minBalance: minBalance,
accounts: make(map[common.Address]*bind.TransactOpts, len(privs)),
numAccounts: len(privs),
accsCh: make(chan *bind.TransactOpts, len(privs)+2),
client: client,
minBalance: minBalance,
accounts: make(map[common.Address]*bind.TransactOpts, len(privs)),
accsCh: make(chan *bind.TransactOpts, len(privs)+2),
}
// get chainID from client

View File

@@ -20,6 +20,8 @@ import (
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"scroll-tech/bridge/utils"
"scroll-tech/bridge/config"
)
@@ -120,6 +122,15 @@ func NewSender(ctx context.Context, config *config.SenderConfig, privs []*ecdsa.
return nil, err
}
var baseFeePerGas uint64
if config.TxType == DynamicFeeTxType {
if header.BaseFee != nil {
baseFeePerGas = header.BaseFee.Uint64()
} else {
return nil, errors.New("DynamicFeeTxType not supported, header.BaseFee nil")
}
}
sender := &Sender{
ctx: ctx,
config: config,
@@ -128,7 +139,7 @@ func NewSender(ctx context.Context, config *config.SenderConfig, privs []*ecdsa.
auths: auths,
confirmCh: make(chan *Confirmation, 128),
blockNumber: header.Number.Uint64(),
baseFeePerGas: header.BaseFee.Uint64(),
baseFeePerGas: baseFeePerGas,
pendingTxs: sync.Map{},
stopCh: make(chan struct{}),
}
@@ -151,7 +162,7 @@ func (s *Sender) ConfirmChan() <-chan *Confirmation {
// NumberOfAccounts return the count of accounts.
func (s *Sender) NumberOfAccounts() int {
return s.auths.numAccounts
return len(s.auths.accounts)
}
func (s *Sender) getFeeData(auth *bind.TransactOpts, target *common.Address, value *big.Int, data []byte) (*FeeData, error) {
@@ -352,11 +363,20 @@ func (s *Sender) resubmitTransaction(feeData *FeeData, auth *bind.TransactOpts,
return s.createAndSendTx(auth, feeData, tx.To(), tx.Value(), tx.Data(), &nonce)
}
// CheckPendingTransaction Check pending transaction given number of blocks to wait before confirmation.
func (s *Sender) CheckPendingTransaction(header *types.Header) {
// checkPendingTransaction checks the confirmation status of pending transactions against the latest confirmed block number.
// If a transaction hasn't been confirmed after a certain number of blocks, it will be resubmitted with an increased gas price.
func (s *Sender) checkPendingTransaction(header *types.Header, confirmed uint64) {
number := header.Number.Uint64()
atomic.StoreUint64(&s.blockNumber, number)
atomic.StoreUint64(&s.baseFeePerGas, header.BaseFee.Uint64())
if s.config.TxType == DynamicFeeTxType {
if header.BaseFee != nil {
atomic.StoreUint64(&s.baseFeePerGas, header.BaseFee.Uint64())
} else {
log.Error("DynamicFeeTxType not supported, header.BaseFee nil")
}
}
s.pendingTxs.Range(func(key, value interface{}) bool {
// ignore empty id, since we use empty id to occupy pending task
if value == nil || reflect.ValueOf(value).IsNil() {
@@ -366,7 +386,7 @@ func (s *Sender) CheckPendingTransaction(header *types.Header) {
pending := value.(*PendingTransaction)
receipt, err := s.client.TransactionReceipt(s.ctx, pending.tx.Hash())
if (err == nil) && (receipt != nil) {
if number >= receipt.BlockNumber.Uint64()+s.config.Confirmations {
if receipt.BlockNumber.Uint64() <= confirmed {
s.pendingTxs.Delete(key)
// send confirm message
s.confirmCh <- &Confirmation{
@@ -440,7 +460,14 @@ func (s *Sender) loop(ctx context.Context) {
log.Error("failed to get latest head", "err", err)
continue
}
s.CheckPendingTransaction(header)
confirmed, err := utils.GetLatestConfirmedBlockNumber(s.ctx, s.client, s.config.Confirmations)
if err != nil {
log.Error("failed to get latest confirmed block number", "err", err)
continue
}
s.checkPendingTransaction(header, confirmed)
case <-checkBalanceTicker.C:
// Check and set balance.
_ = s.auths.checkAndSetBalances(ctx)

View File

@@ -14,6 +14,7 @@ import (
cmap "github.com/orcaman/concurrent-map"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/stretchr/testify/assert"
"scroll-tech/common/docker"
@@ -22,7 +23,7 @@ import (
"scroll-tech/bridge/sender"
)
const TX_BATCH = 50
const TXBatch = 50
var (
privateKeys []*ecdsa.PrivateKey
@@ -68,7 +69,7 @@ func testBatchSender(t *testing.T, batchSize int) {
}
senderCfg := cfg.L1Config.RelayerConfig.SenderConfig
senderCfg.Confirmations = 0
senderCfg.Confirmations = rpc.LatestBlockNumber
newSender, err := sender.NewSender(context.Background(), senderCfg, privateKeys)
if err != nil {
t.Fatal(err)
@@ -84,7 +85,7 @@ func testBatchSender(t *testing.T, batchSize int) {
for idx := 0; idx < newSender.NumberOfAccounts(); idx++ {
index := idx
eg.Go(func() error {
for i := 0; i < TX_BATCH; i++ {
for i := 0; i < TXBatch; i++ {
toAddr := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d")
id := strconv.Itoa(i + index*1000)
_, err := newSender.SendTransaction(id, &toAddr, big.NewInt(1), nil)
@@ -103,7 +104,7 @@ func testBatchSender(t *testing.T, batchSize int) {
if err := eg.Wait(); err != nil {
t.Error(err)
}
t.Logf("successful send batch txs, batch size: %d, total count: %d", newSender.NumberOfAccounts(), TX_BATCH*newSender.NumberOfAccounts())
t.Logf("successful send batch txs, batch size: %d, total count: %d", newSender.NumberOfAccounts(), TXBatch*newSender.NumberOfAccounts())
// avoid 10 mins cause testcase panic
after := time.After(80 * time.Second)

View File

@@ -4,18 +4,20 @@ import (
"context"
"crypto/ecdsa"
"math/big"
"scroll-tech/common/docker"
"testing"
"scroll-tech/bridge/config"
"scroll-tech/bridge/mock_bridge"
"github.com/scroll-tech/go-ethereum/accounts/abi/bind"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/stretchr/testify/assert"
"scroll-tech/bridge/config"
"scroll-tech/bridge/mock_bridge"
"scroll-tech/common/docker"
)
var (
@@ -55,16 +57,20 @@ func setupEnv(t *testing.T) {
var err error
privateKey, err = crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121212"))
assert.NoError(t, err)
messagePrivateKey, err := crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121213"))
assert.NoError(t, err)
rollupPrivateKey, err := crypto.ToECDSA(common.FromHex("1212121212121212121212121212121212121212121212121212121212121214"))
assert.NoError(t, err)
// Load config.
cfg, err = config.NewConfig("../config.json")
assert.NoError(t, err)
cfg.L1Config.Confirmations = 0
cfg.L1Config.RelayerConfig.MessageSenderPrivateKeys = []*ecdsa.PrivateKey{privateKey}
cfg.L1Config.RelayerConfig.RollupSenderPrivateKeys = []*ecdsa.PrivateKey{privateKey}
cfg.L2Config.Confirmations = 0
cfg.L2Config.RelayerConfig.MessageSenderPrivateKeys = []*ecdsa.PrivateKey{privateKey}
cfg.L2Config.RelayerConfig.RollupSenderPrivateKeys = []*ecdsa.PrivateKey{privateKey}
cfg.L1Config.Confirmations = rpc.LatestBlockNumber
cfg.L1Config.RelayerConfig.MessageSenderPrivateKeys = []*ecdsa.PrivateKey{messagePrivateKey}
cfg.L1Config.RelayerConfig.RollupSenderPrivateKeys = []*ecdsa.PrivateKey{rollupPrivateKey}
cfg.L2Config.Confirmations = rpc.LatestBlockNumber
cfg.L2Config.RelayerConfig.MessageSenderPrivateKeys = []*ecdsa.PrivateKey{messagePrivateKey}
cfg.L2Config.RelayerConfig.RollupSenderPrivateKeys = []*ecdsa.PrivateKey{rollupPrivateKey}
// Create l1geth container.
l1gethImg = docker.NewTestL1Docker(t)
@@ -89,6 +95,47 @@ func setupEnv(t *testing.T) {
// Create l1 and l2 auth
l1Auth = prepareAuth(t, l1Client, privateKey)
l2Auth = prepareAuth(t, l2Client, privateKey)
// send some balance to message and rollup sender
transferEther(t, l1Auth, l1Client, messagePrivateKey)
transferEther(t, l1Auth, l1Client, rollupPrivateKey)
transferEther(t, l2Auth, l2Client, messagePrivateKey)
transferEther(t, l2Auth, l2Client, rollupPrivateKey)
}
func transferEther(t *testing.T, auth *bind.TransactOpts, client *ethclient.Client, privateKey *ecdsa.PrivateKey) {
targetAddress := crypto.PubkeyToAddress(privateKey.PublicKey)
gasPrice, err := client.SuggestGasPrice(context.Background())
assert.NoError(t, err)
gasPrice.Mul(gasPrice, big.NewInt(2))
// Get pending nonce
nonce, err := client.PendingNonceAt(context.Background(), auth.From)
assert.NoError(t, err)
// 200 ether should be enough
value, ok := big.NewInt(0).SetString("0xad78ebc5ac6200000", 0)
assert.Equal(t, ok, true)
tx := types.NewTx(&types.LegacyTx{
Nonce: nonce,
To: &targetAddress,
Value: value,
Gas: 500000,
GasPrice: gasPrice,
})
signedTx, err := auth.Signer(auth.From, tx)
assert.NoError(t, err)
err = client.SendTransaction(context.Background(), signedTx)
assert.NoError(t, err)
receipt, err := bind.WaitMined(context.Background(), client, signedTx)
assert.NoError(t, err)
if receipt.Status != types.ReceiptStatusSuccessful {
t.Fatalf("Call failed")
}
}
func free(t *testing.T) {
@@ -150,6 +197,9 @@ func TestFunction(t *testing.T) {
// l1 rollup and watch rollup events
t.Run("TestCommitBatchAndFinalizeBatch", testCommitBatchAndFinalizeBatch)
// l2 message
t.Run("testRelayL2MessageSucceed", testRelayL2MessageSucceed)
t.Cleanup(func() {
free(t)
})

View File

@@ -0,0 +1,174 @@
package tests
import (
"context"
"math/big"
"testing"
"github.com/scroll-tech/go-ethereum/accounts/abi/bind"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/stretchr/testify/assert"
"scroll-tech/database"
"scroll-tech/database/migrate"
"scroll-tech/database/orm"
"scroll-tech/bridge/l1"
"scroll-tech/bridge/l2"
)
func testRelayL2MessageSucceed(t *testing.T) {
// Create db handler and reset db.
db, err := database.NewOrmFactory(cfg.DBConfig)
assert.NoError(t, err)
assert.NoError(t, migrate.ResetDB(db.GetDB().DB))
defer db.Close()
prepareContracts(t)
// Create L2Relayer
l2Cfg := cfg.L2Config
l2Relayer, err := l2.NewLayer2Relayer(context.Background(), db, l2Cfg.RelayerConfig)
assert.NoError(t, err)
defer l2Relayer.Stop()
// Create L2Watcher
confirmations := rpc.LatestBlockNumber
l2Watcher := l2.NewL2WatcherClient(context.Background(), l2Client, confirmations, l2Cfg.BatchProposerConfig, l2Cfg.L2MessengerAddress, db)
// Create L1Watcher
l1Cfg := cfg.L1Config
l1Watcher := l1.NewWatcher(context.Background(), l1Client, 0, confirmations, l1Cfg.L1MessengerAddress, l1Cfg.RollupContractAddress, db)
// send message through l2 messenger contract
nonce, err := l2MessengerInstance.MessageNonce(&bind.CallOpts{})
assert.NoError(t, err)
sendTx, err := l2MessengerInstance.SendMessage(l2Auth, l1Auth.From, big.NewInt(0), common.Hex2Bytes("00112233"), big.NewInt(0))
assert.NoError(t, err)
sendReceipt, err := bind.WaitMined(context.Background(), l2Client, sendTx)
assert.NoError(t, err)
if sendReceipt.Status != types.ReceiptStatusSuccessful || err != nil {
t.Fatalf("Call failed")
}
// l2 watch process events
l2Watcher.FetchContractEvent(sendReceipt.BlockNumber.Uint64())
// check db status
msg, err := db.GetL2MessageByNonce(nonce.Uint64())
assert.NoError(t, err)
assert.Equal(t, msg.Status, orm.MsgPending)
assert.Equal(t, msg.Sender, l2Auth.From.String())
assert.Equal(t, msg.Target, l1Auth.From.String())
// add fake blocks
traces := []*types.BlockTrace{
{
Header: &types.Header{
Number: sendReceipt.BlockNumber,
ParentHash: common.Hash{},
Difficulty: big.NewInt(0),
BaseFee: big.NewInt(0),
},
StorageTrace: &types.StorageTrace{},
},
}
err = db.InsertBlockTraces(traces)
assert.NoError(t, err)
// add fake batch
dbTx, err := db.Beginx()
assert.NoError(t, err)
batchID, err := db.NewBatchInDBTx(dbTx,
&orm.BlockInfo{
Number: traces[0].Header.Number.Uint64(),
Hash: traces[0].Header.Hash().String(),
ParentHash: traces[0].Header.ParentHash.String(),
},
&orm.BlockInfo{
Number: traces[0].Header.Number.Uint64(),
Hash: traces[0].Header.Hash().String(),
ParentHash: traces[0].Header.ParentHash.String(),
},
traces[0].Header.ParentHash.String(), 1, 194676)
assert.NoError(t, err)
err = db.SetBatchIDForBlocksInDBTx(dbTx, []uint64{
traces[0].Header.Number.Uint64(),
traces[0].Header.Number.Uint64()}, batchID)
assert.NoError(t, err)
err = dbTx.Commit()
assert.NoError(t, err)
// add dummy proof
tProof := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
tInstanceCommitments := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
err = db.UpdateProofByID(context.Background(), batchID, tProof, tInstanceCommitments, 100)
assert.NoError(t, err)
err = db.UpdateProvingStatus(batchID, orm.ProvingTaskVerified)
assert.NoError(t, err)
// process pending batch and check status
l2Relayer.ProcessPendingBatches()
status, err := db.GetRollupStatus(batchID)
assert.NoError(t, err)
assert.Equal(t, orm.RollupCommitting, status)
commitTxHash, err := db.GetCommitTxHash(batchID)
assert.NoError(t, err)
assert.Equal(t, true, commitTxHash.Valid)
commitTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(commitTxHash.String))
assert.NoError(t, err)
commitTxReceipt, err := bind.WaitMined(context.Background(), l1Client, commitTx)
assert.NoError(t, err)
assert.Equal(t, len(commitTxReceipt.Logs), 1)
// fetch CommitBatch rollup events
err = l1Watcher.FetchContractEvent(commitTxReceipt.BlockNumber.Uint64())
assert.NoError(t, err)
status, err = db.GetRollupStatus(batchID)
assert.NoError(t, err)
assert.Equal(t, orm.RollupCommitted, status)
// process committed batch and check status
l2Relayer.ProcessCommittedBatches()
status, err = db.GetRollupStatus(batchID)
assert.NoError(t, err)
assert.Equal(t, orm.RollupFinalizing, status)
finalizeTxHash, err := db.GetFinalizeTxHash(batchID)
assert.NoError(t, err)
assert.Equal(t, true, finalizeTxHash.Valid)
finalizeTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(finalizeTxHash.String))
assert.NoError(t, err)
finalizeTxReceipt, err := bind.WaitMined(context.Background(), l1Client, finalizeTx)
assert.NoError(t, err)
assert.Equal(t, len(finalizeTxReceipt.Logs), 1)
// fetch FinalizeBatch events
err = l1Watcher.FetchContractEvent(finalizeTxReceipt.BlockNumber.Uint64())
assert.NoError(t, err)
status, err = db.GetRollupStatus(batchID)
assert.NoError(t, err)
assert.Equal(t, orm.RollupFinalized, status)
// process l2 messages
l2Relayer.ProcessSavedEvents()
msg, err = db.GetL2MessageByNonce(nonce.Uint64())
assert.NoError(t, err)
assert.Equal(t, msg.Status, orm.MsgSubmitted)
relayTxHash, err := db.GetRelayL2MessageTxHash(nonce.Uint64())
assert.NoError(t, err)
assert.Equal(t, true, relayTxHash.Valid)
relayTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(relayTxHash.String))
assert.NoError(t, err)
relayTxReceipt, err := bind.WaitMined(context.Background(), l1Client, relayTx)
assert.NoError(t, err)
assert.Equal(t, len(relayTxReceipt.Logs), 1)
// fetch message relayed events
err = l1Watcher.FetchContractEvent(relayTxReceipt.BlockNumber.Uint64())
assert.NoError(t, err)
msg, err = db.GetL2MessageByNonce(nonce.Uint64())
assert.NoError(t, err)
assert.Equal(t, msg.Status, orm.MsgConfirmed)
}

View File

@@ -34,7 +34,7 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
// Create L1Watcher
l1Cfg := cfg.L1Config
l1Watcher := l1.NewWatcher(context.Background(), l1Client, 0, 0, l1Cfg.L1MessengerAddress, l1Cfg.RollupContractAddress, db)
l1Watcher := l1.NewWatcher(context.Background(), l1Client, 0, l1Cfg.Confirmations, l1Cfg.L1MessengerAddress, l1Cfg.RollupContractAddress, db)
// add some blocks to db
var traces []*types.BlockTrace
@@ -80,6 +80,7 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
// process pending batch and check status
l2Relayer.ProcessPendingBatches()
status, err := db.GetRollupStatus(batchID)
assert.NoError(t, err)
assert.Equal(t, orm.RollupCommitting, status)
@@ -93,7 +94,6 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
assert.Equal(t, len(commitTxReceipt.Logs), 1)
// fetch rollup events
assert.NoError(t, err)
err = l1Watcher.FetchContractEvent(commitTxReceipt.BlockNumber.Uint64())
assert.NoError(t, err)
status, err = db.GetRollupStatus(batchID)
@@ -110,6 +110,7 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
// process committed batch and check status
l2Relayer.ProcessCommittedBatches()
status, err = db.GetRollupStatus(batchID)
assert.NoError(t, err)
assert.Equal(t, orm.RollupFinalizing, status)
@@ -123,7 +124,6 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
assert.Equal(t, len(finalizeTxReceipt.Logs), 1)
// fetch rollup events
assert.NoError(t, err)
err = l1Watcher.FetchContractEvent(finalizeTxReceipt.BlockNumber.Uint64())
assert.NoError(t, err)
status, err = db.GetRollupStatus(batchID)

View File

@@ -0,0 +1,56 @@
package utils
import (
"context"
"fmt"
"math/big"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/rpc"
)
type ethClient interface {
BlockNumber(ctx context.Context) (uint64, error)
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
}
// GetLatestConfirmedBlockNumber get confirmed block number by rpc.BlockNumber type.
func GetLatestConfirmedBlockNumber(ctx context.Context, client ethClient, confirm rpc.BlockNumber) (uint64, error) {
switch true {
case confirm == rpc.SafeBlockNumber || confirm == rpc.FinalizedBlockNumber:
var tag *big.Int
if confirm == rpc.FinalizedBlockNumber {
tag = big.NewInt(int64(rpc.FinalizedBlockNumber))
} else {
tag = big.NewInt(int64(rpc.SafeBlockNumber))
}
header, err := client.HeaderByNumber(ctx, tag)
if err != nil {
return 0, err
}
if !header.Number.IsInt64() {
return 0, fmt.Errorf("received invalid block confirm: %v", header.Number)
}
return header.Number.Uint64(), nil
case confirm == rpc.LatestBlockNumber:
number, err := client.BlockNumber(ctx)
if err != nil {
return 0, err
}
return number, nil
case confirm.Int64() >= 0: // If it's positive integer, consider it as a certain confirm value.
number, err := client.BlockNumber(ctx)
if err != nil {
return 0, err
}
cfmNum := uint64(confirm.Int64())
if number >= cfmNum {
return number - cfmNum, nil
}
return 0, nil
default:
return 0, fmt.Errorf("unknown confirmation type: %v", confirm)
}
}

View File

@@ -0,0 +1,107 @@
package utils_test
import (
"context"
"encoding/json"
"math/big"
"testing"
"github.com/stretchr/testify/assert"
"github.com/scroll-tech/go-ethereum/common/math"
"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/rpc"
"scroll-tech/bridge/utils"
)
var (
tests = []struct {
input string
mustFail bool
expected rpc.BlockNumber
}{
{`"0x"`, true, rpc.BlockNumber(0)},
{`"0x0"`, false, rpc.BlockNumber(0)},
{`"0X1"`, false, rpc.BlockNumber(1)},
{`"0x00"`, true, rpc.BlockNumber(0)},
{`"0x01"`, true, rpc.BlockNumber(0)},
{`"0x1"`, false, rpc.BlockNumber(1)},
{`"0x12"`, false, rpc.BlockNumber(18)},
{`"0x7fffffffffffffff"`, false, rpc.BlockNumber(math.MaxInt64)},
{`"0x8000000000000000"`, true, rpc.BlockNumber(0)},
{"0", true, rpc.BlockNumber(0)},
{`"ff"`, true, rpc.BlockNumber(0)},
{`"safe"`, false, rpc.SafeBlockNumber},
{`"finalized"`, false, rpc.FinalizedBlockNumber},
{`"pending"`, false, rpc.PendingBlockNumber},
{`"latest"`, false, rpc.LatestBlockNumber},
{`"earliest"`, false, rpc.EarliestBlockNumber},
{`someString`, true, rpc.BlockNumber(0)},
{`""`, true, rpc.BlockNumber(0)},
{``, true, rpc.BlockNumber(0)},
}
)
func TestUnmarshalJSON(t *testing.T) {
for i, test := range tests {
var num rpc.BlockNumber
err := json.Unmarshal([]byte(test.input), &num)
if test.mustFail && err == nil {
t.Errorf("Test %d should fail", i)
continue
}
if !test.mustFail && err != nil {
t.Errorf("Test %d should pass but got err: %v", i, err)
continue
}
if num != test.expected {
t.Errorf("Test %d got unexpected value, want %d, got %d", i, test.expected, num)
}
}
}
func TestMarshalJSON(t *testing.T) {
for i, test := range tests {
var num rpc.BlockNumber
want, err := json.Marshal(test.expected)
assert.Nil(t, err)
if !test.mustFail {
err = json.Unmarshal([]byte(test.input), &num)
assert.Nil(t, err)
got, err := json.Marshal(&num)
assert.Nil(t, err)
if string(want) != string(got) {
t.Errorf("Test %d got unexpected value, want %d, got %d", i, test.expected, num)
}
}
}
}
type MockEthClient struct {
val uint64
}
func (e MockEthClient) BlockNumber(ctx context.Context) (uint64, error) {
return e.val, nil
}
func (e MockEthClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
return &types.Header{Number: new(big.Int).SetUint64(e.val)}, nil
}
func TestGetLatestConfirmedBlockNumber(t *testing.T) {
ctx := context.Background()
client := MockEthClient{}
client.val = 5
confirmed, err := utils.GetLatestConfirmedBlockNumber(ctx, &client, 6)
assert.Nil(t, err)
assert.Equal(t, uint64(0), confirmed)
client.val = 7
confirmed, err = utils.GetLatestConfirmedBlockNumber(ctx, &client, 6)
assert.Nil(t, err)
assert.Equal(t, uint64(1), confirmed)
}

View File

@@ -20,8 +20,8 @@ func encodePacked(input ...[]byte) []byte {
// ComputeMessageHash compute the message hash
func ComputeMessageHash(
target common.Address,
sender common.Address,
target common.Address,
value *big.Int,
fee *big.Int,
deadline *big.Int,
@@ -29,8 +29,8 @@ func ComputeMessageHash(
messageNonce *big.Int,
) common.Hash {
packed := encodePacked(
target.Bytes(),
sender.Bytes(),
target.Bytes(),
math.U256Bytes(value),
math.U256Bytes(fee),
math.U256Bytes(deadline),

View File

@@ -7,6 +7,7 @@ import (
"scroll-tech/bridge/utils"
"github.com/scroll-tech/go-ethereum/common"
"github.com/stretchr/testify/assert"
)
func TestKeccak2(t *testing.T) {
@@ -28,15 +29,13 @@ func TestKeccak2(t *testing.T) {
func TestComputeMessageHash(t *testing.T) {
hash := utils.ComputeMessageHash(
common.HexToAddress("0xdafea492d9c6733ae3d56b7ed1adb60692c98bc5"),
common.HexToAddress("0xeafea492d9c6733ae3d56b7ed1adb60692c98bf7"),
big.NewInt(1),
big.NewInt(2),
big.NewInt(1234567),
common.Hex2Bytes("0011223344"),
big.NewInt(3),
common.HexToAddress("0xd7227113b92e537aeda220d5a2f201b836e5879d"),
common.HexToAddress("0x47c02b023b6787ef4e503df42bbb1a94f451a1c0"),
big.NewInt(5000000000000000),
big.NewInt(0),
big.NewInt(1674204924),
common.Hex2Bytes("8eaac8a30000000000000000000000007138b17fc82d7e954b3bd2f98d8166d03e5e569b0000000000000000000000007138b17fc82d7e954b3bd2f98d8166d03e5e569b0000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"),
big.NewInt(30706),
)
if hash != common.HexToHash("0x58c9a5abfd2a558bb6a6fd5192b36fe9325d98763bafd3a51a1ea28a5d0b990b") {
t.Fatalf("Invalid ComputeMessageHash, want %s, got %s", "0x58c9a5abfd2a558bb6a6fd5192b36fe9325d98763bafd3a51a1ea28a5d0b990b", hash.Hex())
}
assert.Equal(t, hash.String(), "0x920e59f62ca89a0f481d44961c55d299dd20c575693692d61fdf3ca579d8edf3")
}

View File

@@ -1,5 +1,5 @@
# Build libzkp dependency
FROM scrolltech/go-rust-builder:go-1.18-rust-nightly-2022-08-23 as chef
FROM scrolltech/go-rust-builder:go-1.18-rust-nightly-2022-12-10 as chef
WORKDIR app
FROM chef as planner
@@ -13,10 +13,11 @@ RUN cargo chef cook --release --recipe-path recipe.json
COPY ./common/libzkp/impl .
RUN cargo build --release
RUN find ./ | grep libzktrie.so | xargs -i cp {} /app/target/release/
# Download Go dependencies
FROM scrolltech/go-rust-builder:go-1.18-rust-nightly-2022-08-23 as base
FROM scrolltech/go-rust-builder:go-1.18-rust-nightly-2022-12-10 as base
WORKDIR /src
COPY go.work* ./
COPY ./bridge/go.* ./bridge/
@@ -33,11 +34,16 @@ FROM base as builder
COPY . .
RUN cp -r ./common/libzkp/interface ./coordinator/verifier/lib
COPY --from=zkp-builder /app/target/release/libzkp.a ./coordinator/verifier/lib/
RUN cd ./coordinator && go build -v -p 4 -o /bin/coordinator ./cmd
COPY --from=zkp-builder /app/target/release/libzktrie.so ./coordinator/verifier/lib/
RUN cd ./coordinator && go build -v -p 4 -o /bin/coordinator ./cmd && mv verifier/lib /bin/
# Pull coordinator into a second stage deploy alpine container
FROM ubuntu:20.04
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/src/coordinator/verifier/lib
# ENV CHAIN_ID=534353
RUN mkdir -p /src/coordinator/verifier/lib
COPY --from=builder /bin/lib /src/coordinator/verifier/lib
COPY --from=builder /bin/coordinator /bin/
ENTRYPOINT ["/bin/coordinator"]

View File

@@ -1,6 +1,6 @@
GO_VERSION := 1.18
PYTHON_VERSION := 3.10
RUST_VERSION := nightly-2022-08-23
RUST_VERSION := nightly-2022-12-10
.PHONY: all go-alpine-builder rust-builder rust-alpine-builder go-rust-alpine-builder go-rust-builder py-runner

View File

@@ -4,4 +4,4 @@ FROM golang:1.18-alpine
# RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add --no-cache gcc musl-dev linux-headers git ca-certificates
RUN apk add --no-cache gcc musl-dev linux-headers git ca-certificates openssl-dev

View File

@@ -1,8 +1,8 @@
FROM golang:1.18-alpine
ARG CARGO_CHEF_TAG=0.1.41
ARG DEFAULT_RUST_TOOLCHAIN=nightly-2022-08-23
ARG DEFAULT_RUST_TOOLCHAIN=nightly-2022-12-10
RUN apk add --no-cache gcc musl-dev linux-headers git ca-certificates
RUN apk add --no-cache gcc musl-dev linux-headers git ca-certificates openssl-dev
# RUN apk add --no-cache libc6-compat
# RUN apk add --no-cache gcompat

View File

@@ -14,7 +14,7 @@ ENV PATH="/root/.cargo/bin:${PATH}"
ENV CARGO_HOME=/root/.cargo
# Add Toolchain
RUN rustup toolchain install nightly-2022-08-23
RUN rustup toolchain install nightly-2022-12-10
# TODO: make this ARG
ENV CARGO_CHEF_TAG=0.1.41

View File

@@ -1,10 +1,11 @@
ARG ALPINE_VERSION=3.15
FROM alpine:${ALPINE_VERSION}
ARG CARGO_CHEF_TAG=0.1.41
ARG DEFAULT_RUST_TOOLCHAIN=nightly-2022-08-23
ARG DEFAULT_RUST_TOOLCHAIN=nightly-2022-12-10
RUN apk add --no-cache \
ca-certificates \
openssl-dev \
gcc \
git \
musl-dev

View File

@@ -13,4 +13,4 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
# Add Toolchain
RUN rustup toolchain install nightly-2022-08-23
RUN rustup toolchain install nightly-2022-12-10

View File

@@ -1,4 +1,4 @@
FROM scrolltech/l2geth:prealpha-v4.2
FROM scrolltech/l2geth:prealpha-v5.1
RUN mkdir -p /l2geth/keystore

View File

@@ -6,19 +6,19 @@ require (
github.com/docker/docker v20.10.21+incompatible
github.com/jmoiron/sqlx v1.3.5
github.com/lib/pq v1.10.6
github.com/mattn/go-colorable v0.1.8
github.com/mattn/go-isatty v0.0.14
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.16
github.com/orcaman/concurrent-map v1.0.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20221221073256-5ca70bf3a257
github.com/scroll-tech/go-ethereum v1.10.14-0.20230220082843-ec9254b0b1c6
github.com/stretchr/testify v1.8.0
github.com/urfave/cli/v2 v2.10.2
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
)
require (
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
@@ -27,11 +27,11 @@ require (
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/ethereum/go-ethereum v1.10.26 // indirect
github.com/ethereum/go-ethereum v1.11.1 // indirect
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.8 // indirect
@@ -48,7 +48,6 @@ require (
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-sqlite3 v1.14.14 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -64,26 +63,25 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.8.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.3.1 // indirect
github.com/scroll-tech/zktrie v0.5.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.4.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/net v0.3.0 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.3.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/urfave/cli.v1 v1.20.0 // indirect

View File

@@ -78,8 +78,8 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -126,15 +126,15 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.10.13/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw=
github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/ethereum/go-ethereum v1.11.1 h1:EMymmWFzpS7G9l9NvVN8G73cgdUIqDPNRf2YTSGBXlk=
github.com/ethereum/go-ethereum v1.11.1/go.mod h1:DuefStAgaxoaYGLR0FueVcVbehmn5n9QUcVrMCuOvuc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
@@ -159,8 +159,9 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
@@ -269,8 +270,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
@@ -287,8 +288,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -308,16 +308,17 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -372,7 +373,6 @@ github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQm
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -396,19 +396,16 @@ github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
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.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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.20221221073256-5ca70bf3a257 h1:FjBC0Ww42WRoiB5EQFxoIEcJqoEUw2twdhN9nGkVCQA=
github.com/scroll-tech/go-ethereum v1.10.14-0.20221221073256-5ca70bf3a257/go.mod h1:jurIpDQ0hqtp9//xxeWzr8X9KMP/+TYn+vz3K1wZrv0=
github.com/scroll-tech/zktrie v0.3.0/go.mod h1:CuJFlG1/soTJJBAySxCZgTF7oPvd5qF6utHOEciC43Q=
github.com/scroll-tech/zktrie v0.3.1 h1:HlR+fMBdjXX1/7cUMqpUgGEhGy/3vN1JpwQ0ovg/Ys8=
github.com/scroll-tech/zktrie v0.3.1/go.mod h1:CuJFlG1/soTJJBAySxCZgTF7oPvd5qF6utHOEciC43Q=
github.com/scroll-tech/go-ethereum v1.10.14-0.20230220082843-ec9254b0b1c6 h1:2kXWJR+mOj09HBh5sUTb4L/OURPSXoQd1NC/10v7otM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20230220082843-ec9254b0b1c6/go.mod h1:eW+eyNdMoO0MyuczCc9xWSnW8dPJ0kOy5xsxgOKYEaA=
github.com/scroll-tech/zktrie v0.5.0 h1:dABDR6lMZq6Hs+fWQSiHbX8s3AOX6hY+5nkhSYm5rmU=
github.com/scroll-tech/zktrie v0.5.0/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -425,8 +422,9 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -448,11 +446,12 @@ github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYa
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
@@ -482,8 +481,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -541,8 +540,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -599,15 +598,15 @@ golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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=
@@ -619,13 +618,14 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/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.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

File diff suppressed because it is too large Load Diff

View File

@@ -7,9 +7,16 @@ edition = "2021"
[lib]
crate-type = ["staticlib"]
[patch."https://github.com/privacy-scaling-explorations/halo2.git"]
halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "scroll-dev-0220" }
[patch."https://github.com/privacy-scaling-explorations/poseidon.git"]
poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "scroll-dev-0220" }
[patch."https://github.com/scroll-tech/zktrie.git"]
zktrie = { git = "https://github.com/lispc/zktrie", branch = "scroll-dev-0215" }
[dependencies]
zkevm = { git = "https://github.com/scroll-tech/scroll-zkevm" }
types = { git = "https://github.com/scroll-tech/scroll-zkevm" }
zkevm = { git = "https://github.com/scroll-tech/scroll-zkevm", branch="goerli-0215" }
types = { git = "https://github.com/scroll-tech/scroll-zkevm", branch="goerli-0215" }
log = "0.4"
env_logger = "0.9.0"

View File

@@ -1 +1 @@
nightly-2022-08-23
nightly-2022-12-10

View File

@@ -44,7 +44,7 @@ pub unsafe extern "C" fn create_agg_proof_multi(trace_char: *const c_char) -> *c
let proof = PROVER
.get_mut()
.unwrap()
.create_agg_circuit_proof_multi(traces.as_slice())
.create_agg_circuit_proof_batch(traces.as_slice())
.unwrap();
let proof_bytes = serde_json::to_vec(&proof).unwrap();
vec_to_c_char(proof_bytes)

View File

@@ -214,8 +214,9 @@ func (z *ProofDetail) Hash() ([]byte, error) {
// AggProof includes the proof and public input that are required to verification and rollup.
type AggProof struct {
Proof []byte `json:"proof"`
Instance []byte `json:"instance"`
FinalPair []byte `json:"final_pair"`
Vk []byte `json:"vk"`
Proof []byte `json:"proof"`
Instance []byte `json:"instance"`
FinalPair []byte `json:"final_pair"`
Vk []byte `json:"vk"`
BlockCount uint `json:"block_count"`
}

53
common/metrics/metrics.go Normal file
View File

@@ -0,0 +1,53 @@
package metrics
import (
"context"
"net"
"net/http"
"strconv"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/metrics/prometheus"
"github.com/scroll-tech/go-ethereum/rpc"
"github.com/urfave/cli/v2"
"scroll-tech/common/utils"
)
// Serve starts the metrics server on the given address, will be closed when the given
// context is canceled.
func Serve(ctx context.Context, c *cli.Context) {
if !c.Bool(utils.MetricsEnabled.Name) {
return
}
address := net.JoinHostPort(
c.String(utils.MetricsAddr.Name),
strconv.Itoa(c.Int(utils.MetricsPort.Name)),
)
server := &http.Server{
Addr: address,
Handler: prometheus.Handler(metrics.DefaultRegistry),
ReadTimeout: rpc.DefaultHTTPTimeouts.ReadTimeout,
WriteTimeout: rpc.DefaultHTTPTimeouts.WriteTimeout,
IdleTimeout: rpc.DefaultHTTPTimeouts.IdleTimeout,
}
go func() {
<-ctx.Done()
if err := server.Close(); err != nil {
log.Error("Failed to close metrics server", "error", err)
}
}()
log.Info("Starting metrics server", "address", address)
go func() {
if err := server.ListenAndServe(); err != nil {
log.Error("start metrics server error", "error", err)
}
}()
}

View File

@@ -12,6 +12,9 @@ var (
&LogFileFlag,
&LogJSONFormat,
&LogDebugFlag,
&MetricsEnabled,
&MetricsAddr,
&MetricsPort,
}
// ConfigFileFlag load json type config file.
ConfigFileFlag = cli.StringFlag{
@@ -42,4 +45,25 @@ var (
Name: "log.debug",
Usage: "Prepends log messages with call-site location (file and line number)",
}
// MetricsEnabled enable metrics collection and reporting
MetricsEnabled = cli.BoolFlag{
Name: "metrics",
Usage: "Enable metrics collection and reporting",
Category: "METRICS",
Value: false,
}
// MetricsAddr is listening address of Metrics reporting server
MetricsAddr = cli.StringFlag{
Name: "metrics.addr",
Usage: "Metrics reporting server listening address",
Category: "METRICS",
Value: "0.0.0.0",
}
// MetricsPort is listening port of Metrics reporting server
MetricsPort = cli.IntFlag{
Name: "metrics.port",
Usage: "Metrics reporting server listening port",
Category: "METRICS",
Value: 6060,
}
)

View File

@@ -38,10 +38,14 @@ func StartHTTPEndpoint(endpoint string, apis []rpc.API) (*http.Server, net.Addr,
}
// StartWSEndpoint starts the WS RPC endpoint.
func StartWSEndpoint(endpoint string, apis []rpc.API) (*http.Server, net.Addr, error) {
func StartWSEndpoint(endpoint string, apis []rpc.API, compressionLevel int) (*http.Server, net.Addr, error) {
handler, addr, err := StartHTTPEndpoint(endpoint, apis)
if err == nil {
srv := (handler.Handler).(*rpc.Server)
err = srv.SetCompressionLevel(compressionLevel)
if err != nil {
log.Error("failed to set ws compression level", "compression level", compressionLevel, "err", err)
}
handler.Handler = srv.WebsocketHandler(nil)
}
return handler, addr, err

View File

@@ -1,6 +1,7 @@
package utils
import (
"compress/flate"
"context"
"testing"
@@ -59,7 +60,7 @@ func TestStartWSEndpoint(t *testing.T) {
Namespace: "test",
Service: new(testService),
},
})
}, flate.NoCompression)
assert.NoError(t, err)
defer handler.Shutdown(context.Background())

View File

@@ -5,7 +5,7 @@ import (
"runtime/debug"
)
var tag = "prealpha-v10.1"
var tag = "alpha-v1.2"
var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {

View File

@@ -13,7 +13,7 @@ The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT in layer 1 and
### batchDepositERC1155
```solidity
function batchDepositERC1155(address _token, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external nonpayable
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.
@@ -32,7 +32,7 @@ Deposit a list of some ERC1155 NFT to caller&#39;s account on layer 2.
### batchDepositERC1155
```solidity
function batchDepositERC1155(address _token, address _to, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external nonpayable
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.
@@ -69,7 +69,7 @@ The address of corresponding L1/L2 Gateway contract.
### depositERC1155
```solidity
function depositERC1155(address _token, address _to, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external nonpayable
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.
@@ -89,7 +89,7 @@ Deposit some ERC1155 NFT to a recipient&#39;s account on layer 2.
### depositERC1155
```solidity
function depositERC1155(address _token, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external nonpayable
function depositERC1155(address _token, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit some ERC1155 NFT to caller&#39;s account on layer 2.
@@ -126,17 +126,6 @@ Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipie
| _tokenIds | uint256[] | The list of token ids to withdraw. |
| _amounts | uint256[] | The list of corresponding number of token to withdraw. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
### finalizeWithdrawERC1155
```solidity
@@ -164,7 +153,7 @@ Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient&#39
function initialize(address _counterpart, address _messenger) external nonpayable
```
Initialize the storage of L1ERC1155Gateway.
@@ -172,8 +161,8 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
| Name | Type | Description |
|---|---|---|
| _counterpart | address | undefined |
| _messenger | address | undefined |
| _counterpart | address | The address of L2ERC1155Gateway in L2. |
| _messenger | address | The address of L1ScrollMessenger. |
### messenger
@@ -181,7 +170,7 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.

View File

@@ -13,7 +13,7 @@ The `L1ERC721Gateway` is used to deposit ERC721 compatible NFT in layer 1 and fi
### batchDepositERC721
```solidity
function batchDepositERC721(address _token, address _to, uint256[] _tokenIds, uint256 _gasLimit) external nonpayable
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.
@@ -32,7 +32,7 @@ Deposit a list of some ERC721 NFT to a recipient&#39;s account on layer 2.
### batchDepositERC721
```solidity
function batchDepositERC721(address _token, uint256[] _tokenIds, uint256 _gasLimit) external nonpayable
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.
@@ -67,7 +67,7 @@ The address of corresponding L1/L2 Gateway contract.
### depositERC721
```solidity
function depositERC721(address _token, address _to, uint256 _tokenId, uint256 _gasLimit) external nonpayable
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.
@@ -86,7 +86,7 @@ Deposit some ERC721 NFT to a recipient&#39;s account on layer 2.
### depositERC721
```solidity
function depositERC721(address _token, uint256 _tokenId, uint256 _gasLimit) external nonpayable
function depositERC721(address _token, uint256 _tokenId, uint256 _gasLimit) external payable
```
Deposit some ERC721 NFT to caller&#39;s account on layer 2.
@@ -121,17 +121,6 @@ Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient
| _to | address | The address of recipient in layer 1 to receive the token. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
### finalizeWithdrawERC721
```solidity
@@ -158,7 +147,7 @@ Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s
function initialize(address _counterpart, address _messenger) external nonpayable
```
Initialize the storage of L1ERC721Gateway.
@@ -166,8 +155,8 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
| Name | Type | Description |
|---|---|---|
| _counterpart | address | undefined |
| _messenger | address | undefined |
| _counterpart | address | The address of L2ERC721Gateway in L2. |
| _messenger | address | The address of L1ScrollMessenger. |
### messenger
@@ -175,7 +164,7 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.

View File

@@ -26,23 +26,6 @@ Mapping from ERC20 token address to corresponding L1ERC20Gateway.
|---|---|---|
| _0 | address | undefined |
#### 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 |
@@ -126,10 +109,10 @@ Deposit some token to a recipient&#39;s account on L2 and call.
### depositETH
```solidity
function depositETH(address _to, uint256 _gasLimit) external payable
function depositETH(uint256 _amount, uint256 _gasLimit) external payable
```
Deposit ETH to recipient&#39;s account in L2.
Deposit ETH to caller&#39;s account in L2.
@@ -137,16 +120,16 @@ Deposit ETH to recipient&#39;s account in L2.
| Name | Type | Description |
|---|---|---|
| _to | address | The address of recipient&#39;s account on L2. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### depositETH
```solidity
function depositETH(uint256 _gasLimit) external payable
function depositETH(address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Deposit ETH to call&#39;s account in L2.
Deposit ETH to some recipient&#39;s account in L2.
@@ -154,18 +137,45 @@ Deposit ETH to call&#39;s account in L2.
| Name | Type | Description |
|---|---|---|
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### finalizeDropMessage
### depositETHAndCall
```solidity
function finalizeDropMessage() external payable
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
@@ -191,21 +201,21 @@ Complete ERC20 withdraw from L2 to L1 and send fund to recipient&#39;s account i
### finalizeWithdrawETH
```solidity
function finalizeWithdrawETH(address _from, address _to, uint256 _amount, bytes _data) external payable
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 L2GatewayRouter in L2.*
*This function should only be called by L1ScrollMessenger. This function should also only be called by L1ETHGateway in L2.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | The address of account who withdraw ETH in L2. |
| _to | address | The address of recipient in L1 to receive ETH. |
| _amount | uint256 | The amount of ETH to withdraw. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | bytes | undefined |
### getERC20Gateway
@@ -254,10 +264,10 @@ Return the corresponding l2 token address given l1 token address.
### initialize
```solidity
function initialize(address _defaultERC20Gateway, address _counterpart, address _messenger) external nonpayable
function initialize(address _ethGateway, address _defaultERC20Gateway) external nonpayable
```
Initialize the storage of L1GatewayRouter.
@@ -265,26 +275,8 @@ function initialize(address _defaultERC20Gateway, address _counterpart, address
| Name | Type | Description |
|---|---|---|
| _defaultERC20Gateway | address | undefined |
| _counterpart | address | undefined |
| _messenger | address | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
| _ethGateway | address | The address of L1ETHGateway contract. |
| _defaultERC20Gateway | address | The address of default ERC20 Gateway contract. |
### owner
@@ -314,23 +306,6 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing 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 |
### setDefaultERC20Gateway
```solidity
@@ -364,6 +339,22 @@ Update the mapping from token address to gateway address.
| _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 _ethGateway) external nonpayable
```
Update the address of ETH gateway contract.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _ethGateway | address | The address to update. |
### transferOwnership
```solidity
@@ -387,10 +378,10 @@ function transferOwnership(address newOwner) external nonpayable
### DepositERC20
```solidity
event DepositERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -398,20 +389,20 @@ event DepositERC20(address indexed _l1Token, address indexed _l2Token, address i
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### DepositETH
```solidity
event DepositETH(address indexed _from, address indexed _to, uint256 _amount, bytes _data)
event DepositETH(address indexed from, address indexed to, uint256 amount, bytes data)
```
Emitted when someone deposit ETH from L1 to L2.
@@ -419,18 +410,18 @@ event DepositETH(address indexed _from, address indexed _to, uint256 _amount, by
| Name | Type | Description |
|---|---|---|
| _from `indexed` | address | undefined |
| _to `indexed` | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| from `indexed` | address | undefined |
| to `indexed` | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### FinalizeWithdrawERC20
```solidity
event FinalizeWithdrawERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -438,20 +429,20 @@ event FinalizeWithdrawERC20(address indexed _l1Token, address indexed _l2Token,
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### FinalizeWithdrawETH
```solidity
event FinalizeWithdrawETH(address indexed _from, address indexed _to, uint256 _amount, bytes _data)
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.
@@ -459,10 +450,10 @@ event FinalizeWithdrawETH(address indexed _from, address indexed _to, uint256 _a
| Name | Type | Description |
|---|---|---|
| _from `indexed` | address | undefined |
| _to `indexed` | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| from `indexed` | address | undefined |
| to `indexed` | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### OwnershipTransferred
@@ -484,10 +475,10 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn
### SetDefaultERC20Gateway
```solidity
event SetDefaultERC20Gateway(address indexed _defaultERC20Gateway)
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway)
```
Emitted when the address of default ERC20 Gateway is updated.
@@ -495,15 +486,15 @@ event SetDefaultERC20Gateway(address indexed _defaultERC20Gateway)
| Name | Type | Description |
|---|---|---|
| _defaultERC20Gateway `indexed` | address | undefined |
| defaultERC20Gateway `indexed` | address | undefined |
### SetERC20Gateway
```solidity
event SetERC20Gateway(address indexed _token, address indexed _gateway)
event SetERC20Gateway(address indexed token, address indexed gateway)
```
Emitted when the `gateway` for `token` is updated.
@@ -511,8 +502,24 @@ event SetERC20Gateway(address indexed _token, address indexed _gateway)
| Name | Type | Description |
|---|---|---|
| _token `indexed` | address | undefined |
| _gateway `indexed` | address | undefined |
| token `indexed` | address | undefined |
| gateway `indexed` | address | undefined |
### SetETHGateway
```solidity
event SetETHGateway(address indexed ethGateway)
```
Emitted when the address of ETH Gateway is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| ethGateway `indexed` | address | undefined |

View File

@@ -10,13 +10,13 @@ The `L1ScrollMessenger` contract can: 1. send messages from layer 1 to layer 2;
## Methods
### dropDelayDuration
### counterpart
```solidity
function dropDelayDuration() external view returns (uint256)
function counterpart() external view returns (address)
```
The amount of seconds needed to wait if we want to drop message.
The address of counterpart ScrollMessenger contract in L1/L2.
@@ -25,38 +25,15 @@ The amount of seconds needed to wait if we want to drop message.
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
| _0 | address | undefined |
### dropMessage
### feeVault
```solidity
function dropMessage(address _from, address _to, uint256 _value, uint256 _fee, uint256 _deadline, uint256 _nonce, bytes _message, uint256 _gasLimit) external nonpayable
function feeVault() external view returns (address)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _fee | uint256 | undefined |
| _deadline | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
### gasOracle
```solidity
function gasOracle() external view returns (address)
```
The gas oracle used to estimate transaction fee on layer 2.
The address of fee vault, collecting cross domain messaging fee.
@@ -70,10 +47,10 @@ The gas oracle used to estimate transaction fee on layer 2.
### initialize
```solidity
function initialize(address _rollup) external nonpayable
function initialize(address _counterpart, address _feeVault, address _rollup, address _messageQueue) external nonpayable
```
Initialize the storage of L1ScrollMessenger.
@@ -81,56 +58,15 @@ function initialize(address _rollup) external nonpayable
| Name | Type | Description |
|---|---|---|
| _rollup | address | undefined |
| _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. |
### isMessageDropped
### isL1MessageRelayed
```solidity
function isMessageDropped(bytes32) external view returns (bool)
```
Mapping from message hash to drop status.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### isMessageExecuted
```solidity
function isMessageExecuted(bytes32) external view returns (bool)
```
Mapping from message hash to execution status.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### isMessageRelayed
```solidity
function isMessageRelayed(bytes32) external view returns (bool)
function isL1MessageRelayed(bytes32) external view returns (bool)
```
Mapping from relay id to relay status.
@@ -149,6 +85,67 @@ Mapping from relay id to relay status.
|---|---|---|
| _0 | bool | undefined |
### isL1MessageSent
```solidity
function isL1MessageSent(bytes32) external view returns (bool)
```
Mapping from L1 message hash to sent 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 |
### messageQueue
```solidity
function messageQueue() external view returns (address)
```
The address of L1MessageQueue contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### owner
```solidity
@@ -197,7 +194,7 @@ function paused() external view returns (bool)
### relayMessageWithProof
```solidity
function relayMessageWithProof(address _from, address _to, uint256 _value, uint256 _fee, uint256 _deadline, uint256 _nonce, bytes _message, IL1ScrollMessenger.L2MessageProof _proof) external nonpayable
function relayMessageWithProof(address _from, address _to, uint256 _value, uint256 _nonce, bytes _message, IL1ScrollMessenger.L2MessageProof _proof) external nonpayable
```
@@ -211,8 +208,6 @@ function relayMessageWithProof(address _from, address _to, uint256 _value, uint2
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _fee | uint256 | undefined |
| _deadline | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
| _proof | IL1ScrollMessenger.L2MessageProof | undefined |
@@ -231,7 +226,7 @@ function renounceOwnership() external nonpayable
### replayMessage
```solidity
function replayMessage(address _from, address _to, uint256 _value, uint256 _fee, uint256 _deadline, bytes _message, uint256 _queueIndex, uint32 _oldGasLimit, uint32 _newGasLimit) external nonpayable
function replayMessage(address _from, address _to, uint256 _value, uint256 _queueIndex, bytes _message, uint32 _oldGasLimit, uint32 _newGasLimit) external nonpayable
```
Replay an exsisting message.
@@ -242,15 +237,13 @@ Replay an exsisting message.
| Name | Type | Description |
|---|---|---|
| _from | address | The address of the sender of the message. |
| _to | address | The address of the recipient of the message. |
| _value | uint256 | The msg.value passed to the message call. |
| _fee | uint256 | The amount of fee in ETH to charge. |
| _deadline | uint256 | The deadline of the message. |
| _message | bytes | The content of the message. |
| _queueIndex | uint256 | CTC Queue index for the message to replay. |
| _oldGasLimit | uint32 | Original gas limit used to send the message. |
| _newGasLimit | uint32 | New gas limit to be used for this message. |
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _queueIndex | uint256 | undefined |
| _message | bytes | undefined |
| _oldGasLimit | uint32 | undefined |
| _newGasLimit | uint32 | undefined |
### rollup
@@ -272,21 +265,21 @@ The address of Rollup contract.
### sendMessage
```solidity
function sendMessage(address _to, uint256 _fee, bytes _message, uint256 _gasLimit) external payable
function sendMessage(address _to, uint256 _value, bytes _message, uint256 _gasLimit) external payable
```
Send cross chain message (L1 =&gt; L2 or L2 =&gt; L1)
Send cross chain message from L1 to L2 or L2 to L1.
*Currently, only privileged accounts can call this function for safty. And adding an extra `_fee` variable make it more easy to upgrade to decentralized version.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | The address of account who recieve the message. |
| _fee | uint256 | The amount of fee in Ether the caller would like to pay to the relayer. |
| _message | bytes | The content of the message. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _to | address | undefined |
| _value | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
### transferOwnership
@@ -304,13 +297,13 @@ function transferOwnership(address newOwner) external nonpayable
|---|---|---|
| newOwner | address | undefined |
### updateDropDelayDuration
### updateFeeVault
```solidity
function updateDropDelayDuration(uint256 _newDuration) external nonpayable
function updateFeeVault(address _newFeeVault) external nonpayable
```
Update the drop delay duration.
Update fee vault contract.
*This function can only called by contract owner.*
@@ -318,23 +311,7 @@ Update the drop delay duration.
| Name | Type | Description |
|---|---|---|
| _newDuration | uint256 | The new delay duration to update. |
### updateGasOracle
```solidity
function updateGasOracle(address _newGasOracle) external nonpayable
```
Update the address of gas oracle.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newGasOracle | address | The address to update. |
| _newFeeVault | address | The address of new fee vault contract. |
### updateWhitelist
@@ -393,10 +370,10 @@ See {IScrollMessenger-xDomainMessageSender}
### FailedRelayedMessage
```solidity
event FailedRelayedMessage(bytes32 indexed msgHash)
event FailedRelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is failed to relay.
@@ -404,23 +381,7 @@ event FailedRelayedMessage(bytes32 indexed msgHash)
| Name | Type | Description |
|---|---|---|
| msgHash `indexed` | bytes32 | undefined |
### MessageDropped
```solidity
event MessageDropped(bytes32 indexed msgHash)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| msgHash `indexed` | bytes32 | undefined |
| messageHash `indexed` | bytes32 | undefined |
### OwnershipTransferred
@@ -458,10 +419,10 @@ event Paused(address account)
### RelayedMessage
```solidity
event RelayedMessage(bytes32 indexed msgHash)
event RelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is relayed successfully.
@@ -469,15 +430,15 @@ event RelayedMessage(bytes32 indexed msgHash)
| Name | Type | Description |
|---|---|---|
| msgHash `indexed` | bytes32 | undefined |
| messageHash `indexed` | bytes32 | undefined |
### SentMessage
```solidity
event SentMessage(address indexed target, address sender, uint256 value, uint256 fee, uint256 deadline, bytes message, uint256 messageNonce, uint256 gasLimit)
event SentMessage(address indexed sender, address indexed target, uint256 value, uint256 messageNonce, uint256 gasLimit, bytes message)
```
Emitted when a cross domain message is sent.
@@ -485,14 +446,12 @@ event SentMessage(address indexed target, address sender, uint256 value, uint256
| Name | Type | Description |
|---|---|---|
| sender `indexed` | address | undefined |
| target `indexed` | address | undefined |
| sender | address | undefined |
| value | uint256 | undefined |
| fee | uint256 | undefined |
| deadline | uint256 | undefined |
| message | bytes | undefined |
| messageNonce | uint256 | undefined |
| gasLimit | uint256 | undefined |
| message | bytes | undefined |
### Unpaused
@@ -510,13 +469,13 @@ event Unpaused(address account)
|---|---|---|
| account | address | undefined |
### UpdateDropDelayDuration
### UpdateFeeVault
```solidity
event UpdateDropDelayDuration(uint256 _oldDuration, uint256 _newDuration)
event UpdateFeeVault(address _oldFeeVault, address _newFeeVault)
```
Emitted when owner updates drop delay duration
Emitted when owner updates fee vault contract.
@@ -524,25 +483,8 @@ Emitted when owner updates drop delay duration
| Name | Type | Description |
|---|---|---|
| _oldDuration | uint256 | undefined |
| _newDuration | uint256 | undefined |
### UpdateGasOracle
```solidity
event UpdateGasOracle(address _oldGasOracle, address _newGasOracle)
```
Emitted when owner updates gas oracle contract.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _oldGasOracle | address | undefined |
| _newGasOracle | address | undefined |
| _oldFeeVault | address | undefined |
| _newFeeVault | address | undefined |
### UpdateWhitelist

View File

@@ -84,17 +84,6 @@ Deposit some token to a recipient&#39;s account on L2 and call.
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
### finalizeWithdrawERC20
```solidity
@@ -144,7 +133,7 @@ Return the corresponding l2 token address given l1 token address.
function initialize(address _counterpart, address _router, address _messenger, address _l2TokenImplementation, address _l2TokenFactory) external nonpayable
```
Initialize the storage of L1StandardERC20Gateway.
@@ -152,11 +141,11 @@ function initialize(address _counterpart, address _router, address _messenger, a
| Name | Type | Description |
|---|---|---|
| _counterpart | address | undefined |
| _router | address | undefined |
| _messenger | address | undefined |
| _l2TokenImplementation | address | undefined |
| _l2TokenFactory | address | undefined |
| _counterpart | address | The address of L2StandardERC20Gateway in L2. |
| _router | address | The address of L1GatewayRouter. |
| _messenger | address | The address of L1ScrollMessenger. |
| _l2TokenImplementation | address | The address of ScrollStandardERC20 implementation in L2. |
| _l2TokenFactory | address | The address of ScrollStandardERC20Factory contract in L2. |
### l2TokenFactory
@@ -198,7 +187,7 @@ The address of ScrollStandardERC20 implementation in L2.
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
@@ -233,10 +222,10 @@ The address of L1GatewayRouter/L2GatewayRouter contract.
### DepositERC20
```solidity
event DepositERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -244,20 +233,20 @@ event DepositERC20(address indexed _l1Token, address indexed _l2Token, address i
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### FinalizeWithdrawERC20
```solidity
event FinalizeWithdrawERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -265,12 +254,12 @@ event FinalizeWithdrawERC20(address indexed _l1Token, address indexed _l2Token,
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |

View File

@@ -101,17 +101,6 @@ Deposit some token to a recipient&#39;s account on L2 and call.
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Gas limit required to complete the deposit on L2. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
### finalizeWithdrawERC20
```solidity
@@ -158,10 +147,10 @@ Return the corresponding l2 token address given l1 token address.
### initialize
```solidity
function initialize(address _counterpart, address _router, address _messenger, address _WETH, address _l2WETH) external nonpayable
function initialize(address _counterpart, address _router, address _messenger) external nonpayable
```
Initialize the storage of L1WETHGateway.
@@ -169,11 +158,9 @@ function initialize(address _counterpart, address _router, address _messenger, a
| Name | Type | Description |
|---|---|---|
| _counterpart | address | undefined |
| _router | address | undefined |
| _messenger | address | undefined |
| _WETH | address | undefined |
| _l2WETH | address | undefined |
| _counterpart | address | The address of L2ETHGateway in L2. |
| _router | address | The address of L1GatewayRouter. |
| _messenger | address | The address of L1ScrollMessenger. |
### l2WETH
@@ -198,7 +185,7 @@ The address of L2 WETH address.
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
@@ -233,10 +220,10 @@ The address of L1GatewayRouter/L2GatewayRouter contract.
### DepositERC20
```solidity
event DepositERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -244,20 +231,20 @@ event DepositERC20(address indexed _l1Token, address indexed _l2Token, address i
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### FinalizeWithdrawERC20
```solidity
event FinalizeWithdrawERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -265,12 +252,12 @@ event FinalizeWithdrawERC20(address indexed _l1Token, address indexed _l2Token,
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |

View File

@@ -16,7 +16,7 @@ The `L2ERC1155Gateway` is used to withdraw ERC1155 compatible NFTs in layer 2 an
function batchWithdrawERC1155(address _token, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external nonpayable
```
Batch withdraw a list of ERC1155 NFT to caller&#39;s account on layer 1.
@@ -35,7 +35,7 @@ function batchWithdrawERC1155(address _token, uint256[] _tokenIds, uint256[] _am
function batchWithdrawERC1155(address _token, address _to, uint256[] _tokenIds, uint256[] _amounts, uint256 _gasLimit) external nonpayable
```
Batch withdraw a list of ERC1155 NFT to caller&#39;s account on layer 1.
@@ -72,9 +72,9 @@ The address of corresponding L1/L2 Gateway contract.
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 in layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway in layer 1.*
#### Parameters
@@ -93,9 +93,9 @@ function finalizeBatchDepositERC1155(address _l1Token, address _l2Token, address
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 in layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway in layer 1.*
#### Parameters
@@ -108,17 +108,6 @@ function finalizeDepositERC1155(address _l1Token, address _l2Token, address _fro
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
### initialize
```solidity
@@ -142,7 +131,7 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
@@ -333,7 +322,7 @@ Update layer 2 to layer 1 token mapping.
function withdrawERC1155(address _token, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external nonpayable
```
Withdraw some ERC1155 NFT to caller&#39;s account on layer 1.
@@ -352,7 +341,7 @@ function withdrawERC1155(address _token, uint256 _tokenId, uint256 _amount, uint
function withdrawERC1155(address _token, address _to, uint256 _tokenId, uint256 _amount, uint256 _gasLimit) external nonpayable
```
Withdraw some ERC1155 NFT to caller&#39;s account on layer 1.
@@ -373,10 +362,10 @@ function withdrawERC1155(address _token, address _to, uint256 _tokenId, uint256
### BatchWithdrawERC1155
```solidity
event BatchWithdrawERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds, uint256[] _amounts)
event BatchWithdrawERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds, uint256[] amounts)
```
Emitted when the ERC1155 NFT is batch transfered to gateway in layer 2.
@@ -384,20 +373,20 @@ event BatchWithdrawERC1155(address indexed _l1Token, address indexed _l2Token, a
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| _amounts | uint256[] | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenIds | uint256[] | undefined |
| amounts | uint256[] | undefined |
### FinalizeBatchDepositERC1155
```solidity
event FinalizeBatchDepositERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds, uint256[] _amounts)
event FinalizeBatchDepositERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds, uint256[] amounts)
```
Emitted when the ERC1155 NFT is batch transfered to recipient in layer 2.
@@ -405,20 +394,20 @@ event FinalizeBatchDepositERC1155(address indexed _l1Token, address indexed _l2T
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| _amounts | uint256[] | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenIds | uint256[] | undefined |
| amounts | uint256[] | undefined |
### FinalizeDepositERC1155
```solidity
event FinalizeDepositERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId, uint256 _amount)
event FinalizeDepositERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId, uint256 amount)
```
Emitted when the ERC1155 NFT is transfered to recipient in layer 2.
@@ -426,12 +415,12 @@ event FinalizeDepositERC1155(address indexed _l1Token, address indexed _l2Token,
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenId | uint256 | undefined |
| amount | uint256 | undefined |
### OwnershipTransferred
@@ -470,10 +459,10 @@ Emitted when token mapping for ERC1155 token is updated.
### WithdrawERC1155
```solidity
event WithdrawERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId, uint256 _amount)
event WithdrawERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId, uint256 amount)
```
Emitted when the ERC1155 NFT is transfered to gateway in layer 2.
@@ -481,12 +470,12 @@ event WithdrawERC1155(address indexed _l1Token, address indexed _l2Token, addres
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenId | uint256 | undefined |
| amount | uint256 | undefined |

View File

@@ -24,9 +24,9 @@ Batch withdraw a list of ERC721 NFT to caller&#39;s account on layer 1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 2. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _tokenIds | uint256[] | undefined |
| _gasLimit | uint256 | undefined |
### batchWithdrawERC721
@@ -42,10 +42,10 @@ Batch withdraw a list of ERC721 NFT to caller&#39;s account on layer 1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 2. |
| _to | address | The address of recipient in layer 1. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| _gasLimit | uint256 | undefined |
### counterpart
@@ -78,11 +78,11 @@ Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s
| 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 in layer 1. |
| _to | address | The address of recipient in layer 2 to receive the token. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
### finalizeDepositERC721
@@ -98,22 +98,11 @@ Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s
| 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 in layer 1. |
| _to | address | The address of recipient in layer 2 to receive the token. |
| _tokenId | uint256 | The token id to withdraw. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
### initialize
@@ -138,7 +127,7 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
@@ -288,9 +277,9 @@ Withdraw some ERC721 NFT to caller&#39;s account on layer 1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 2. |
| _tokenId | uint256 | The token id to withdraw. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _tokenId | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC721
@@ -306,10 +295,10 @@ Withdraw some ERC721 NFT to caller&#39;s account on layer 1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 2. |
| _to | address | The address of recipient in layer 1. |
| _tokenId | uint256 | The token id to withdraw. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| _gasLimit | uint256 | undefined |
@@ -318,7 +307,7 @@ Withdraw some ERC721 NFT to caller&#39;s account on layer 1.
### BatchWithdrawERC721
```solidity
event BatchWithdrawERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds)
event BatchWithdrawERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds)
```
Emitted when the ERC721 NFT is batch transfered to gateway in layer 2.
@@ -329,16 +318,16 @@ Emitted when the ERC721 NFT is batch transfered to gateway in layer 2.
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenIds | uint256[] | undefined |
### FinalizeBatchDepositERC721
```solidity
event FinalizeBatchDepositERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds)
event FinalizeBatchDepositERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds)
```
Emitted when the ERC721 NFT is batch transfered to recipient in layer 2.
@@ -349,16 +338,16 @@ Emitted when the ERC721 NFT is batch transfered to recipient in layer 2.
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenIds | uint256[] | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenIds | uint256[] | undefined |
### FinalizeDepositERC721
```solidity
event FinalizeDepositERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId)
event FinalizeDepositERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId)
```
Emitted when the ERC721 NFT is transfered to recipient in layer 2.
@@ -369,11 +358,11 @@ Emitted when the ERC721 NFT is transfered to recipient in layer 2.
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenId | uint256 | undefined |
### OwnershipTransferred
@@ -412,7 +401,7 @@ Emitted when token mapping for ERC721 token is updated.
### WithdrawERC721
```solidity
event WithdrawERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId)
event WithdrawERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId)
```
Emitted when the ERC721 NFT is transfered to gateway in layer 2.
@@ -423,11 +412,11 @@ Emitted when the ERC721 NFT is transfered to gateway in layer 2.
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _tokenId | uint256 | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| tokenId | uint256 | undefined |

View File

@@ -32,13 +32,13 @@ Mapping from L2 ERC20 token address to corresponding L2ERC20Gateway.
|---|---|---|
| _0 | address | undefined |
### counterpart
### defaultERC20Gateway
```solidity
function counterpart() external view returns (address)
function defaultERC20Gateway() external view returns (address)
```
The address of corresponding L1/L2 Gateway contract.
The addess of default L2 ERC20 gateway, normally the L2StandardERC20Gateway contract.
@@ -49,13 +49,13 @@ The address of corresponding L1/L2 Gateway contract.
|---|---|---|
| _0 | address | undefined |
### defaultERC20Gateway
### ethGateway
```solidity
function defaultERC20Gateway() external view returns (address)
function ethGateway() external view returns (address)
```
The addess of default L2 ERC20 gateway, normally the L2StandardERC20Gateway contract.
The address of L2ETHGateway.
@@ -90,7 +90,7 @@ Complete a deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
### finalizeDepositETH
```solidity
function finalizeDepositETH(address _from, address _to, uint256 _amount, bytes _data) external payable
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.
@@ -101,21 +101,10 @@ Complete ETH deposit from L1 to L2 and send fund to recipient&#39;s account in L
| Name | Type | Description |
|---|---|---|
| _from | address | The address of account who deposit ETH in L1. |
| _to | address | The address of recipient in L2 to receive ETH. |
| _amount | uint256 | The amount of ETH to deposit. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
| _0 | address | undefined |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | bytes | undefined |
### getERC20Gateway
@@ -186,7 +175,7 @@ Return the corresponding l2 token address given l1 token address.
### initialize
```solidity
function initialize(address _defaultERC20Gateway, address _counterpart, address _messenger) external nonpayable
function initialize(address _ethGateway, address _defaultERC20Gateway) external nonpayable
```
@@ -197,26 +186,8 @@ function initialize(address _defaultERC20Gateway, address _counterpart, address
| Name | Type | Description |
|---|---|---|
| _ethGateway | address | undefined |
| _defaultERC20Gateway | address | undefined |
| _counterpart | address | undefined |
| _messenger | address | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### owner
@@ -246,23 +217,6 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing 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 |
### setDefaultERC20Gateway
```solidity
@@ -296,6 +250,22 @@ Update the mapping from token address to gateway address.
| _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 _ethGateway) external nonpayable
```
Update the address of ETH gateway contract.
*This function should only be called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _ethGateway | address | The address to update. |
### transferOwnership
```solidity
@@ -326,9 +296,9 @@ Withdraw of some token to a caller&#39;s account on L1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20
@@ -344,10 +314,10 @@ Withdraw of some token to a recipient&#39;s account on L1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _to | address | The address of recipient&#39;s account on L1. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20AndCall
@@ -363,16 +333,16 @@ Withdraw of some token to a recipient&#39;s account on L1 and call.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _to | address | The address of recipient&#39;s account on L1. |
| _amount | uint256 | The amount of token to transfer. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
### withdrawETH
```solidity
function withdrawETH(address _to, uint256 _gasLimit) external payable
function withdrawETH(address _to, uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw ETH to caller&#39;s account in L1.
@@ -383,13 +353,14 @@ Withdraw ETH to caller&#39;s account in L1.
| Name | Type | Description |
|---|---|---|
| _to | address | The address of recipient&#39;s account on L1. |
| _gasLimit | uint256 | Gas limit required to complete the withdraw on L1. |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawETH
```solidity
function withdrawETH(uint256 _gasLimit) external payable
function withdrawETH(uint256 _amount, uint256 _gasLimit) external payable
```
Withdraw ETH to caller&#39;s account in L1.
@@ -400,7 +371,27 @@ Withdraw ETH to caller&#39;s account in L1.
| Name | Type | Description |
|---|---|---|
| _gasLimit | uint256 | Gas limit required to complete the withdraw on L1. |
| _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 |
@@ -409,10 +400,10 @@ Withdraw ETH to caller&#39;s account in L1.
### FinalizeDepositERC20
```solidity
event FinalizeDepositERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -420,20 +411,20 @@ event FinalizeDepositERC20(address indexed _l1Token, address indexed _l2Token, a
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### FinalizeDepositETH
```solidity
event FinalizeDepositETH(address indexed _from, address indexed _to, uint256 _amount, bytes _data)
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.
@@ -441,10 +432,10 @@ event FinalizeDepositETH(address indexed _from, address indexed _to, uint256 _am
| Name | Type | Description |
|---|---|---|
| _from `indexed` | address | undefined |
| _to `indexed` | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| from `indexed` | address | undefined |
| to `indexed` | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### OwnershipTransferred
@@ -466,10 +457,10 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn
### SetDefaultERC20Gateway
```solidity
event SetDefaultERC20Gateway(address indexed _defaultERC20Gateway)
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway)
```
Emitted when the address of default ERC20 Gateway is updated.
@@ -477,15 +468,15 @@ event SetDefaultERC20Gateway(address indexed _defaultERC20Gateway)
| Name | Type | Description |
|---|---|---|
| _defaultERC20Gateway `indexed` | address | undefined |
| defaultERC20Gateway `indexed` | address | undefined |
### SetERC20Gateway
```solidity
event SetERC20Gateway(address indexed _token, address indexed _gateway)
event SetERC20Gateway(address indexed token, address indexed gateway)
```
Emitted when the `gateway` for `token` is updated.
@@ -493,16 +484,32 @@ event SetERC20Gateway(address indexed _token, address indexed _gateway)
| Name | Type | Description |
|---|---|---|
| _token `indexed` | address | undefined |
| _gateway `indexed` | address | undefined |
| token `indexed` | address | undefined |
| gateway `indexed` | address | undefined |
### SetETHGateway
```solidity
event SetETHGateway(address indexed ethGateway)
```
Emitted when the address of ETH Gateway is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| ethGateway `indexed` | address | undefined |
### WithdrawERC20
```solidity
event WithdrawERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -510,20 +517,20 @@ event WithdrawERC20(address indexed _l1Token, address indexed _l2Token, address
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### WithdrawETH
```solidity
event WithdrawETH(address indexed _from, address indexed _to, uint256 _amount, bytes _data)
event WithdrawETH(address indexed from, address indexed to, uint256 amount, bytes data)
```
Emitted when someone withdraw ETH from L2 to L1.
@@ -531,10 +538,10 @@ event WithdrawETH(address indexed _from, address indexed _to, uint256 _amount, b
| Name | Type | Description |
|---|---|---|
| _from `indexed` | address | undefined |
| _to `indexed` | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| from `indexed` | address | undefined |
| to `indexed` | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |

View File

@@ -10,13 +10,13 @@ The `L2ScrollMessenger` contract can: 1. send messages from layer 2 to layer 1;
## Methods
### dropDelayDuration
### blockContainer
```solidity
function dropDelayDuration() external view returns (uint256)
function blockContainer() external view returns (address)
```
The amount of seconds needed to wait if we want to drop message.
The contract contains the list of L1 blocks.
@@ -25,30 +25,41 @@ The amount of seconds needed to wait if we want to drop message.
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
| _0 | address | undefined |
### dropMessage
### counterpart
```solidity
function dropMessage(address, address, uint256, uint256, uint256, uint256, bytes, uint256) external nonpayable
function counterpart() external view returns (address)
```
The address of counterpart ScrollMessenger contract in L1/L2.
#### Parameters
#### 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 |
| _1 | address | undefined |
| _2 | uint256 | undefined |
| _3 | uint256 | undefined |
| _4 | uint256 | undefined |
| _5 | uint256 | undefined |
| _6 | bytes | undefined |
| _7 | uint256 | undefined |
### gasOracle
@@ -56,7 +67,7 @@ function dropMessage(address, address, uint256, uint256, uint256, uint256, bytes
function gasOracle() external view returns (address)
```
The gas oracle used to estimate transaction fee on layer 2.
The address of L2MessageQueue.
@@ -67,13 +78,30 @@ The gas oracle used to estimate transaction fee on layer 2.
|---|---|---|
| _0 | address | undefined |
### isMessageExecuted
### initialize
```solidity
function isMessageExecuted(bytes32) external view returns (bool)
function initialize(address _counterpart, address _feeVault) external nonpayable
```
Mapping from message hash to execution status.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _counterpart | address | undefined |
| _feeVault | 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.
@@ -89,13 +117,13 @@ Mapping from message hash to execution status.
|---|---|---|
| _0 | bool | undefined |
### isMessageRelayed
### isL2MessageSent
```solidity
function isMessageRelayed(bytes32) external view returns (bool)
function isL2MessageSent(bytes32) external view returns (bool)
```
Mapping from relay id to relay status.
Mapping from L2 message hash to sent status.
@@ -111,13 +139,35 @@ Mapping from relay id to relay status.
|---|---|---|
| _0 | bool | undefined |
### messageNonce
### l1MessageFailedTimes
```solidity
function messageNonce() external view returns (uint256)
function l1MessageFailedTimes(bytes32) external view returns (uint256)
```
Message nonce, used to avoid relay attack.
Mapping from L1 message hash to the number of failure times.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### maxFailedExecutionTimes
```solidity
function maxFailedExecutionTimes() external view returns (uint256)
```
The maximum number of times each L1 message can fail on L2.
@@ -128,30 +178,13 @@ Message nonce, used to avoid relay attack.
|---|---|---|
| _0 | uint256 | undefined |
### messagePasser
### messageQueue
```solidity
function messagePasser() external view returns (contract L2ToL1MessagePasser)
function messageQueue() external view returns (address)
```
Contract to store the sent message.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | contract L2ToL1MessagePasser | undefined |
### owner
```solidity
function owner() external view returns (address)
```
The address of the current owner.
The address of L2MessageQueue.
@@ -162,10 +195,55 @@ The address of the current owner.
|---|---|---|
| _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 |
### pause
```solidity
function pause() external nonpayable
```
Pause the contract
*This function can only called by contract owner.*
### 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 _fee, uint256 _deadline, uint256 _nonce, bytes _message) external nonpayable
function relayMessage(address _from, address _to, uint256 _value, uint256 _nonce, bytes _message) external nonpayable
```
execute L1 =&gt; L2 message
@@ -176,13 +254,11 @@ execute L1 =&gt; L2 message
| Name | Type | Description |
|---|---|---|
| _from | address | The address of the sender of the message. |
| _to | address | The address of the recipient of the message. |
| _value | uint256 | The msg.value passed to the message call. |
| _fee | uint256 | The amount of fee in ETH to charge. |
| _deadline | uint256 | The deadline of the message. |
| _nonce | uint256 | The nonce of the message to avoid replay attack. |
| _message | bytes | The content of the message. |
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
### renounceOwnership
@@ -190,53 +266,74 @@ execute L1 =&gt; L2 message
function renounceOwnership() external nonpayable
```
Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner.
*Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
### retryMessageWithProof
```solidity
function retryMessageWithProof(address _from, address _to, uint256 _value, uint256 _nonce, bytes _message, IL2ScrollMessenger.L1MessageProof _proof) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
| _proof | IL2ScrollMessenger.L1MessageProof | undefined |
### sendMessage
```solidity
function sendMessage(address _to, uint256 _fee, bytes _message, uint256 _gasLimit) external payable
function sendMessage(address _to, uint256 _value, bytes _message, uint256 _gasLimit) external payable
```
Send cross chain message (L1 =&gt; L2 or L2 =&gt; L1)
Send cross chain message from L1 to L2 or L2 to L1.
*Currently, only privileged accounts can call this function for safty. And adding an extra `_fee` variable make it more easy to upgrade to decentralized version.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _to | address | The address of account who recieve the message. |
| _fee | uint256 | The amount of fee in Ether the caller would like to pay to the relayer. |
| _message | bytes | The content of the message. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _to | address | undefined |
| _value | uint256 | undefined |
| _message | bytes | undefined |
| _gasLimit | uint256 | undefined |
### transferOwnership
```solidity
function transferOwnership(address _newOwner) external nonpayable
function transferOwnership(address newOwner) external nonpayable
```
Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.
*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 |
| newOwner | address | undefined |
### updateDropDelayDuration
### updateFeeVault
```solidity
function updateDropDelayDuration(uint256 _newDuration) external nonpayable
function updateFeeVault(address _newFeeVault) external nonpayable
```
Update the drop delay duration.
Update fee vault contract.
*This function can only called by contract owner.*
@@ -244,23 +341,23 @@ Update the drop delay duration.
| Name | Type | Description |
|---|---|---|
| _newDuration | uint256 | The new delay duration to update. |
| _newFeeVault | address | The address of new fee vault contract. |
### updateGasOracle
### updateMaxFailedExecutionTimes
```solidity
function updateGasOracle(address _newGasOracle) external nonpayable
function updateMaxFailedExecutionTimes(uint256 _maxFailedExecutionTimes) external nonpayable
```
Update the address of gas oracle.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newGasOracle | address | The address to update. |
| _maxFailedExecutionTimes | uint256 | undefined |
### updateWhitelist
@@ -278,6 +375,54 @@ Update whitelist contract.
|---|---|---|
| _newWhitelist | address | The address of new whitelist contract. |
### verifyMessageExecutionStatus
```solidity
function verifyMessageExecutionStatus(bytes32 _blockHash, bytes32 _msgHash, bytes _proof) external view returns (bool)
```
Check whether the message is executed in the corresponding L1 block.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _blockHash | bytes32 | The block hash where the message should in. |
| _msgHash | bytes32 | The hash of the message to check. |
| _proof | bytes | The encoded storage proof from eth_getProof. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | bool Return true is the message is executed in L1, otherwise return false. |
### verifyMessageInclusionStatus
```solidity
function verifyMessageInclusionStatus(bytes32 _blockHash, bytes32 _msgHash, bytes _proof) external view returns (bool)
```
Check whether the l1 message is included in the corresponding L1 block.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _blockHash | bytes32 | The block hash where the message should in. |
| _msgHash | bytes32 | The hash of the message to check. |
| _proof | bytes | The encoded storage proof from eth_getProof. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | bool Return true is the message is included in L1, otherwise return false. |
### whitelist
```solidity
@@ -319,10 +464,10 @@ See {IScrollMessenger-xDomainMessageSender}
### FailedRelayedMessage
```solidity
event FailedRelayedMessage(bytes32 indexed msgHash)
event FailedRelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is failed to relay.
@@ -330,31 +475,15 @@ event FailedRelayedMessage(bytes32 indexed msgHash)
| Name | Type | Description |
|---|---|---|
| msgHash `indexed` | bytes32 | undefined |
### MessageDropped
```solidity
event MessageDropped(bytes32 indexed msgHash)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| msgHash `indexed` | bytes32 | undefined |
| messageHash `indexed` | bytes32 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed _oldOwner, address indexed _newOwner)
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
Emitted when owner is changed by current owner.
@@ -362,16 +491,32 @@ Emitted when owner is changed by current owner.
| Name | Type | Description |
|---|---|---|
| _oldOwner `indexed` | address | undefined |
| _newOwner `indexed` | address | undefined |
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### Paused
```solidity
event Paused(address account)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| account | address | undefined |
### RelayedMessage
```solidity
event RelayedMessage(bytes32 indexed msgHash)
event RelayedMessage(bytes32 indexed messageHash)
```
Emitted when a cross domain message is relayed successfully.
@@ -379,15 +524,15 @@ event RelayedMessage(bytes32 indexed msgHash)
| Name | Type | Description |
|---|---|---|
| msgHash `indexed` | bytes32 | undefined |
| messageHash `indexed` | bytes32 | undefined |
### SentMessage
```solidity
event SentMessage(address indexed target, address sender, uint256 value, uint256 fee, uint256 deadline, bytes message, uint256 messageNonce, uint256 gasLimit)
event SentMessage(address indexed sender, address indexed target, uint256 value, uint256 messageNonce, uint256 gasLimit, bytes message)
```
Emitted when a cross domain message is sent.
@@ -395,22 +540,20 @@ event SentMessage(address indexed target, address sender, uint256 value, uint256
| Name | Type | Description |
|---|---|---|
| sender `indexed` | address | undefined |
| target `indexed` | address | undefined |
| sender | address | undefined |
| value | uint256 | undefined |
| fee | uint256 | undefined |
| deadline | uint256 | undefined |
| message | bytes | undefined |
| messageNonce | uint256 | undefined |
| gasLimit | uint256 | undefined |
| message | bytes | undefined |
### UpdateDropDelayDuration
### Unpaused
```solidity
event UpdateDropDelayDuration(uint256 _oldDuration, uint256 _newDuration)
event Unpaused(address account)
```
Emitted when owner updates drop delay duration
@@ -418,16 +561,15 @@ Emitted when owner updates drop delay duration
| Name | Type | Description |
|---|---|---|
| _oldDuration | uint256 | undefined |
| _newDuration | uint256 | undefined |
| account | address | undefined |
### UpdateGasOracle
### UpdateFeeVault
```solidity
event UpdateGasOracle(address _oldGasOracle, address _newGasOracle)
event UpdateFeeVault(address _oldFeeVault, address _newFeeVault)
```
Emitted when owner updates gas oracle contract.
Emitted when owner updates fee vault contract.
@@ -435,8 +577,24 @@ Emitted when owner updates gas oracle contract.
| Name | Type | Description |
|---|---|---|
| _oldGasOracle | address | undefined |
| _newGasOracle | address | undefined |
| _oldFeeVault | address | undefined |
| _newFeeVault | address | undefined |
### UpdateMaxFailedExecutionTimes
```solidity
event UpdateMaxFailedExecutionTimes(uint256 maxFailedExecutionTimes)
```
Emitted when the maximum number of times each message can fail in L2 is updated.
#### Parameters
| Name | Type | Description |
|---|---|---|
| maxFailedExecutionTimes | uint256 | The new maximum number of times each message can fail in L2. |
### UpdateWhitelist

View File

@@ -41,23 +41,12 @@ Complete a deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
| 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 deposits the token in L1. |
| _to | address | The address of recipient in L2 to receive the token. |
| _amount | uint256 | The amount of the token to deposit. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
### getL1ERC20Address
@@ -73,7 +62,7 @@ Return the corresponding l1 token address given l2 token address.
| Name | Type | Description |
|---|---|---|
| _l2Token | address | The address of l2 token. |
| _l2Token | address | undefined |
#### Returns
@@ -95,7 +84,7 @@ Return the corresponding l2 token address given l1 token address.
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of l1 token. |
| _l1Token | address | undefined |
#### Returns
@@ -128,7 +117,7 @@ function initialize(address _counterpart, address _router, address _messenger, a
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
@@ -187,9 +176,9 @@ Withdraw of some token to a caller&#39;s account on L1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20
@@ -205,10 +194,10 @@ Withdraw of some token to a recipient&#39;s account on L1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _to | address | The address of recipient&#39;s account on L1. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20AndCall
@@ -224,11 +213,11 @@ Withdraw of some token to a recipient&#39;s account on L1 and call.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _to | address | The address of recipient&#39;s account on L1. |
| _amount | uint256 | The amount of token to transfer. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
@@ -237,10 +226,10 @@ Withdraw of some token to a recipient&#39;s account on L1 and call.
### FinalizeDepositERC20
```solidity
event FinalizeDepositERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -248,20 +237,20 @@ event FinalizeDepositERC20(address indexed _l1Token, address indexed _l2Token, a
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### WithdrawERC20
```solidity
event WithdrawERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -269,12 +258,12 @@ event WithdrawERC20(address indexed _l1Token, address indexed _l2Token, address
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |

View File

@@ -58,23 +58,12 @@ Complete a deposit from L1 to L2 and send fund to recipient&#39;s account in L2.
| 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 deposits the token in L1. |
| _to | address | The address of recipient in L2 to receive the token. |
| _amount | uint256 | The amount of the token to deposit. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
### finalizeDropMessage
```solidity
function finalizeDropMessage() external payable
```
| _l1Token | address | undefined |
| _l2Token | address | undefined |
| _from | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
### getL1ERC20Address
@@ -123,7 +112,7 @@ Return the corresponding l2 token address given l1 token address.
### initialize
```solidity
function initialize(address _counterpart, address _router, address _messenger, address _WETH, address _l1WETH) external nonpayable
function initialize(address _counterpart, address _router, address _messenger) external nonpayable
```
@@ -137,8 +126,6 @@ function initialize(address _counterpart, address _router, address _messenger, a
| _counterpart | address | undefined |
| _router | address | undefined |
| _messenger | address | undefined |
| _WETH | address | undefined |
| _l1WETH | address | undefined |
### l1WETH
@@ -163,7 +150,7 @@ The address of L1 WETH address.
function messenger() external view returns (address)
```
The address of L1ScrollMessenger/L2ScrollMessenger contract.
The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
@@ -205,9 +192,9 @@ Withdraw of some token to a caller&#39;s account on L1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20
@@ -223,10 +210,10 @@ Withdraw of some token to a recipient&#39;s account on L1.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _to | address | The address of recipient&#39;s account on L1. |
| _amount | uint256 | The amount of token to transfer. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _gasLimit | uint256 | undefined |
### withdrawERC20AndCall
@@ -242,11 +229,11 @@ Withdraw of some token to a recipient&#39;s account on L1 and call.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of token in L2. |
| _to | address | The address of recipient&#39;s account on L1. |
| _amount | uint256 | The amount of token to transfer. |
| _data | bytes | Optional data to forward to recipient&#39;s account. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
| _token | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| _gasLimit | uint256 | undefined |
@@ -255,10 +242,10 @@ Withdraw of some token to a recipient&#39;s account on L1 and call.
### FinalizeDepositERC20
```solidity
event FinalizeDepositERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -266,20 +253,20 @@ event FinalizeDepositERC20(address indexed _l1Token, address indexed _l2Token, a
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |
### WithdrawERC20
```solidity
event WithdrawERC20(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _amount, bytes _data)
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.
@@ -287,12 +274,12 @@ event WithdrawERC20(address indexed _l1Token, address indexed _l2Token, address
| Name | Type | Description |
|---|---|---|
| _l1Token `indexed` | address | undefined |
| _l2Token `indexed` | address | undefined |
| _from `indexed` | address | undefined |
| _to | address | undefined |
| _amount | uint256 | undefined |
| _data | bytes | undefined |
| l1Token `indexed` | address | undefined |
| l2Token `indexed` | address | undefined |
| from `indexed` | address | undefined |
| to | address | undefined |
| amount | uint256 | undefined |
| data | bytes | undefined |

View File

@@ -1,594 +0,0 @@
# ZKRollup
> ZKRollup
This contract maintains essential data for zk rollup, including: 1. a list of pending messages, which will be relayed to layer 2; 2. the block tree generated by layer 2 and it&#39;s status.
*the message queue is not used yet, the offline relayer only use events in `L1ScrollMessenger`.*
## Methods
### appendMessage
```solidity
function appendMessage(address _sender, address _target, uint256 _value, uint256 _fee, uint256 _deadline, bytes _message, uint256 _gasLimit) external nonpayable returns (uint256)
```
Append a cross chain message to message queue.
*This function should only be called by L1ScrollMessenger for safety.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _sender | address | The address of message sender in layer 1. |
| _target | address | The address of message recipient in layer 2. |
| _value | uint256 | The amount of ether sent to recipient in layer 2. |
| _fee | uint256 | The amount of ether paid to relayer in layer 2. |
| _deadline | uint256 | The deadline of the message. |
| _message | bytes | The content of the message. |
| _gasLimit | uint256 | Unused, but included for potential forward compatibility considerations. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### batches
```solidity
function batches(bytes32) external view returns (bytes32 batchHash, bytes32 parentHash, uint64 batchIndex, bool verified)
```
Mapping from batch id to batch struct.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| batchHash | bytes32 | undefined |
| parentHash | bytes32 | undefined |
| batchIndex | uint64 | undefined |
| verified | bool | undefined |
### blocks
```solidity
function blocks(bytes32) external view returns (bytes32 parentHash, bytes32 transactionRoot, uint64 blockHeight, uint64 batchIndex)
```
Mapping from block hash to block struct.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| parentHash | bytes32 | undefined |
| transactionRoot | bytes32 | undefined |
| blockHeight | uint64 | undefined |
| batchIndex | uint64 | undefined |
### commitBatch
```solidity
function commitBatch(IZKRollup.Layer2Batch _batch) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batch | IZKRollup.Layer2Batch | undefined |
### finalizeBatchWithProof
```solidity
function finalizeBatchWithProof(bytes32 _batchId, uint256[] _proof, uint256[] _instances) external nonpayable
```
finalize commited batch in layer 1
*will add more parameters if needed.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batchId | bytes32 | The identification of the commited batch. |
| _proof | uint256[] | The corresponding proof of the commited batch. |
| _instances | uint256[] | Instance used to verify, generated from batch. |
### finalizedBatches
```solidity
function finalizedBatches(uint256) external view returns (bytes32)
```
Mapping from batch index to finalized batch id.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
### getMessageHashByIndex
```solidity
function getMessageHashByIndex(uint256 _index) external view returns (bytes32)
```
Return the message hash by index.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _index | uint256 | The index to query. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
### getNextQueueIndex
```solidity
function getNextQueueIndex() external view returns (uint256)
```
Return the index of the first queue element not yet executed.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### getQeueuLength
```solidity
function getQeueuLength() external view returns (uint256)
```
Return the total number of appended message.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### importGenesisBlock
```solidity
function importGenesisBlock(IZKRollup.Layer2BlockHeader _genesis) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _genesis | IZKRollup.Layer2BlockHeader | undefined |
### initialize
```solidity
function initialize(uint256 _chainId) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _chainId | uint256 | undefined |
### isBlockFinalized
```solidity
function isBlockFinalized(bytes32 _blockHash) external view returns (bool)
```
Return whether the block is finalized by block hash.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _blockHash | bytes32 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### isBlockFinalized
```solidity
function isBlockFinalized(uint256 _blockHeight) external view returns (bool)
```
Return whether the block is finalized by block height.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _blockHeight | uint256 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
### lastFinalizedBatchID
```solidity
function lastFinalizedBatchID() external view returns (bytes32)
```
The latest finalized batch id.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | undefined |
### layer2ChainId
```solidity
function layer2ChainId() external view returns (uint256)
```
The chain id of the corresponding layer 2 chain.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### layer2GasLimit
```solidity
function layer2GasLimit(uint256) external view returns (uint256)
```
Return the layer 2 block gas limit.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |
### messenger
```solidity
function messenger() external view returns (address)
```
The address of L1ScrollMessenger.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### operator
```solidity
function operator() external view returns (address)
```
The address of operator.
#### 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 anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
### revertBatch
```solidity
function revertBatch(bytes32 _batchId) external nonpayable
```
revert a pending batch.
*one can only revert unfinalized batches.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batchId | bytes32 | The identification of the batch. |
### 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 |
### updateMessenger
```solidity
function updateMessenger(address _newMessenger) external nonpayable
```
Update the address of messenger.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newMessenger | address | The new messenger address to update. |
### updateOperator
```solidity
function updateOperator(address _newOperator) external nonpayable
```
Update the address of operator.
*This function can only called by contract owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _newOperator | address | The new operator address to update. |
### verifyMessageStateProof
```solidity
function verifyMessageStateProof(uint256 _batchIndex, uint256 _blockHeight) external view returns (bool)
```
Verify a state proof for message relay.
*add more fields.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batchIndex | uint256 | undefined |
| _blockHeight | uint256 | undefined |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined |
## Events
### CommitBatch
```solidity
event CommitBatch(bytes32 indexed _batchId, bytes32 _batchHash, uint256 _batchIndex, bytes32 _parentHash)
```
Emitted when a new batch is commited.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batchId `indexed` | bytes32 | undefined |
| _batchHash | bytes32 | undefined |
| _batchIndex | uint256 | undefined |
| _parentHash | bytes32 | undefined |
### FinalizeBatch
```solidity
event FinalizeBatch(bytes32 indexed _batchId, bytes32 _batchHash, uint256 _batchIndex, bytes32 _parentHash)
```
Emitted when a batch is finalized.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batchId `indexed` | bytes32 | undefined |
| _batchHash | bytes32 | undefined |
| _batchIndex | uint256 | undefined |
| _parentHash | bytes32 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RevertBatch
```solidity
event RevertBatch(bytes32 indexed _batchId)
```
Emitted when a batch is reverted.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _batchId `indexed` | bytes32 | undefined |
### UpdateMesssenger
```solidity
event UpdateMesssenger(address _oldMesssenger, address _newMesssenger)
```
Emitted when owner updates address of messenger
#### Parameters
| Name | Type | Description |
|---|---|---|
| _oldMesssenger | address | The address of old messenger contract. |
| _newMesssenger | address | The address of new messenger contract. |
### UpdateOperator
```solidity
event UpdateOperator(address _oldOperator, address _newOperator)
```
Emitted when owner updates address of operator
#### Parameters
| Name | Type | Description |
|---|---|---|
| _oldOperator | address | The address of old operator. |
| _newOperator | address | The address of new operator. |

View File

@@ -1,826 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { constants } from "ethers";
import { keccak256 } from "ethers/lib/utils";
import { ethers } from "hardhat";
import {
ZKRollup,
L1ScrollMessenger,
L2ScrollMessenger,
L1StandardERC20Gateway,
L2StandardERC20Gateway,
MockERC20,
ScrollStandardERC20Factory,
ScrollStandardERC20,
L1WETHGateway,
L2WETHGateway,
WETH9,
} from "../typechain";
describe("ERC20Gateway", async () => {
const layer1GasLimit = 12345;
const layer2GasLimit = 54321;
const DROP_DELAY_DURATION = 86400 * 7;
let deployer: SignerWithAddress;
let alice: SignerWithAddress;
let bob: SignerWithAddress;
let router: SignerWithAddress;
let rollup: ZKRollup;
let l1Messenger: L1ScrollMessenger;
let l2Messenger: L2ScrollMessenger;
beforeEach(async () => {
[deployer, alice, bob, router] = await ethers.getSigners();
const RollupVerifier = await ethers.getContractFactory("RollupVerifier", deployer);
const verifier = await RollupVerifier.deploy();
await verifier.deployed();
// deploy ZKRollup in layer 1
const ZKRollup = await ethers.getContractFactory("ZKRollup", {
signer: deployer,
libraries: { RollupVerifier: verifier.address },
});
rollup = (await ZKRollup.deploy()) as ZKRollup;
await rollup.initialize(233);
await rollup.importGenesisBlock({
blockHash: keccak256(constants.HashZero),
parentHash: constants.HashZero,
baseFee: 0,
stateRoot: constants.HashZero,
blockHeight: 0,
gasUsed: 0,
timestamp: 0,
extraData: "0x",
txs: [],
});
// deploy L1ScrollMessenger in layer 1
const L1ScrollMessenger = await ethers.getContractFactory("L1ScrollMessenger", deployer);
l1Messenger = await L1ScrollMessenger.deploy();
await l1Messenger.initialize(rollup.address);
await rollup.updateMessenger(l1Messenger.address);
// deploy L2ScrollMessenger in layer 2
const L2ScrollMessenger = await ethers.getContractFactory("L2ScrollMessenger", deployer);
l2Messenger = await L2ScrollMessenger.deploy(deployer.address);
});
context("StandardERC20Gateway", async () => {
let l1Gateway: L1StandardERC20Gateway;
let l2Gateway: L2StandardERC20Gateway;
let factory: ScrollStandardERC20Factory;
beforeEach(async () => {
// deploy token template in layer 2
const ScrollStandardERC20 = await ethers.getContractFactory("ScrollStandardERC20", deployer);
const tokenImpl = await ScrollStandardERC20.deploy();
// deploy token factory in layer 2
const ScrollStandardERC20Factory = await ethers.getContractFactory("ScrollStandardERC20Factory", deployer);
factory = await ScrollStandardERC20Factory.deploy(tokenImpl.address);
// deploy gateway in layer 1
const L1StandardERC20Gateway = await ethers.getContractFactory("L1StandardERC20Gateway", deployer);
l1Gateway = await L1StandardERC20Gateway.deploy();
// deploy gateway in layer 2
const L2StandardERC20Gateway = await ethers.getContractFactory("L2StandardERC20Gateway", deployer);
l2Gateway = await L2StandardERC20Gateway.deploy();
// initialize gateway in layer 1
await l1Gateway.initialize(
l2Gateway.address,
router.address,
l1Messenger.address,
tokenImpl.address,
factory.address
);
// initialize gateway in layer 2
await l2Gateway.initialize(l1Gateway.address, router.address, l2Messenger.address, factory.address);
await factory.transferOwnership(l2Gateway.address);
});
const run1to2 = async (decimals: number, sendToSelf: boolean) => {
context(`layer 1 to layer 2: decimals[${decimals}], sendToSelf[${sendToSelf}]`, async () => {
let l1Token: MockERC20;
let l2Token: ScrollStandardERC20;
let recipient: SignerWithAddress;
const amount1 = ethers.utils.parseUnits("1000", decimals);
const amount2 = ethers.utils.parseUnits("100", decimals);
beforeEach(async () => {
recipient = sendToSelf ? alice : bob;
// deploy mock token in layer 1
const MockERC20 = await ethers.getContractFactory("MockERC20", deployer);
l1Token = await MockERC20.deploy("XYZ", "ZYX", decimals);
await l1Token.mint(alice.address, amount1.add(amount2));
// calculate l2 token address
l2Token = await ethers.getContractAt(
"ScrollStandardERC20",
await l2Gateway.getL2ERC20Address(l1Token.address),
deployer
);
});
it("should succeed, when transfer on the first time", async () => {
// 1. approve
await l1Token.connect(alice).approve(l1Gateway.address, amount1);
// 2. do deposit
const nonce = await rollup.getQeueuLength();
const beforeBalanceLayer1 = await l1Token.balanceOf(l1Gateway.address);
const depositTx = sendToSelf
? await l1Gateway
.connect(alice)
["depositERC20(address,uint256,uint256)"](l1Token.address, amount1, layer1GasLimit)
: await l1Gateway
.connect(alice)
["depositERC20(address,address,uint256,uint256)"](
l1Token.address,
recipient.address,
amount1,
layer1GasLimit
);
await depositTx.wait();
const afterBalanceLayer1 = await l1Token.balanceOf(l1Gateway.address);
// should emit DepositERC20
await expect(depositTx)
.to.emit(l1Gateway, "DepositERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount1, "0x");
// should emit SentMessage
const symbol = await l1Token.symbol();
const name = await l1Token.name();
const deployData = ethers.utils.defaultAbiCoder.encode(
["string", "string", "uint8"],
[symbol, name, decimals]
);
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l2Gateway.interface.encodeFunctionData("finalizeDepositERC20", [
l1Token.address,
l2Token.address,
alice.address,
recipient.address,
amount1,
ethers.utils.defaultAbiCoder.encode(["bytes", "bytes"], ["0x", deployData]),
]);
await expect(depositTx)
.to.emit(l1Messenger, "SentMessage")
.withArgs(l2Gateway.address, l1Gateway.address, 0, 0, deadline, messageData, nonce, layer1GasLimit);
// should transfer token in gateway
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount1);
// 3. do relay in layer 2
const beforeBalanceLayer2 = constants.Zero;
const relayTx = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
0,
0,
deadline,
nonce,
messageData
);
await relayTx.wait();
const afterBalanceLayer2 = await l2Token.balanceOf(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l2Messenger, "RelayedMessage");
// should emit FinalizeDepositERC20
await expect(relayTx)
.to.emit(l2Gateway, "FinalizeDepositERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount1, "0x");
// should deploy token in layer 2
expect(await l2Token.symbol()).to.eq(symbol);
expect(await l2Token.name()).to.eq(name);
expect(await l2Token.decimals()).to.eq(decimals);
// should mint in layer 2
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount1);
});
it("should succeed, when transfer on the second time", async () => {
// 1. approve first time
await l1Token.connect(alice).approve(l1Gateway.address, amount1);
// 2. do deposit first time
const nonce1 = await rollup.getQeueuLength();
let beforeBalanceLayer1 = await l1Token.balanceOf(l1Gateway.address);
const depositTx1 = sendToSelf
? await l1Gateway
.connect(alice)
["depositERC20(address,uint256,uint256)"](l1Token.address, amount1, layer1GasLimit)
: await l1Gateway
.connect(alice)
["depositERC20(address,address,uint256,uint256)"](
l1Token.address,
recipient.address,
amount1,
layer1GasLimit
);
await depositTx1.wait();
let afterBalanceLayer1 = await l1Token.balanceOf(l1Gateway.address);
const symbol = await l1Token.symbol();
const name = await l1Token.name();
const deployData = ethers.utils.defaultAbiCoder.encode(
["string", "string", "uint8"],
[symbol, name, decimals]
);
const deadline1 = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData1 = l2Gateway.interface.encodeFunctionData("finalizeDepositERC20", [
l1Token.address,
l2Token.address,
alice.address,
recipient.address,
amount1,
ethers.utils.defaultAbiCoder.encode(["bytes", "bytes"], ["0x", deployData]),
]);
// should transfer token in gateway
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount1);
// 3. do relay in layer 2 first time
let beforeBalanceLayer2 = constants.Zero;
const relayTx1 = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
0,
0,
deadline1,
nonce1,
messageData1
);
await relayTx1.wait();
let afterBalanceLayer2 = await l2Token.balanceOf(recipient.address);
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount1);
// 4. approve second time
await l1Token.connect(alice).approve(l1Gateway.address, amount2);
// 5. do deposit second time
const calldata = "0x000033";
const nonce2 = await rollup.getQeueuLength();
beforeBalanceLayer1 = await l1Token.balanceOf(l1Gateway.address);
const depositTx2 = await l1Gateway
.connect(alice)
.depositERC20AndCall(l1Token.address, recipient.address, amount2, calldata, layer1GasLimit);
await depositTx2.wait();
afterBalanceLayer1 = await l1Token.balanceOf(l1Gateway.address);
// should emit DepositERC20
await expect(depositTx2)
.to.emit(l1Gateway, "DepositERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount2, calldata);
// should emit SentMessage
const deadline2 = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData2 = l2Gateway.interface.encodeFunctionData("finalizeDepositERC20", [
l1Token.address,
l2Token.address,
alice.address,
recipient.address,
amount2,
calldata,
]);
await expect(depositTx2)
.to.emit(l1Messenger, "SentMessage")
.withArgs(l2Gateway.address, l1Gateway.address, 0, 0, deadline2, messageData2, nonce2, layer1GasLimit);
// should transfer token in gateway
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount2);
// 3. do relay in layer 2
beforeBalanceLayer2 = await l2Token.balanceOf(recipient.address);
const relayTx2 = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
0,
0,
deadline2,
nonce2,
messageData2
);
await relayTx2.wait();
afterBalanceLayer2 = await l2Token.balanceOf(recipient.address);
// should emit RelayedMessage
await expect(relayTx2).to.emit(l2Messenger, "RelayedMessage");
// should emit FinalizeDepositERC20
await expect(relayTx2)
.to.emit(l2Gateway, "FinalizeDepositERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount2, calldata);
// should mint in layer 2
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount2);
});
});
};
const run2to1 = async (decimals: number, sendToSelf: boolean) => {
context(`layer 2 to layer 1: decimals[${decimals}], sendToSelf[${sendToSelf}]`, async () => {
let l1Token: MockERC20;
let l2Token: ScrollStandardERC20;
let recipient: SignerWithAddress;
const amount = ethers.utils.parseUnits("1000", decimals);
beforeEach(async () => {
recipient = sendToSelf ? alice : bob;
// deploy mock token in layer 1
const MockERC20 = await ethers.getContractFactory("MockERC20", deployer);
l1Token = await MockERC20.deploy("XYZ", "ZYX", decimals);
await l1Token.mint(alice.address, amount);
// calculate l2 token address
l2Token = await ethers.getContractAt(
"ScrollStandardERC20",
await l2Gateway.getL2ERC20Address(l1Token.address),
deployer
);
await l1Token.connect(alice).approve(l1Gateway.address, constants.MaxUint256);
const depositTx = await l1Gateway
.connect(alice)
["depositERC20(address,uint256,uint256)"](l1Token.address, amount, layer1GasLimit);
await depositTx.wait();
const symbol = await l1Token.symbol();
const name = await l1Token.name();
const deployData = ethers.utils.defaultAbiCoder.encode(
["string", "string", "uint8"],
[symbol, name, decimals]
);
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const nonce = await rollup.getQeueuLength();
const messageData = l2Gateway.interface.encodeFunctionData("finalizeDepositERC20", [
l1Token.address,
l2Token.address,
alice.address,
alice.address,
amount,
ethers.utils.defaultAbiCoder.encode(["bytes", "bytes"], ["0x", deployData]),
]);
const relayTx = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
0,
0,
deadline,
nonce,
messageData
);
await relayTx.wait();
expect(await l2Token.balanceOf(alice.address)).to.eq(amount);
});
it("should succeed, when transfer without data", async () => {
// 1. approve
await l2Token.connect(alice).approve(l2Gateway.address, amount);
// 2. withdraw
const nonce = await l2Messenger.messageNonce();
const balanceBefore = await l2Token.balanceOf(alice.address);
const withdrawTx = sendToSelf
? await l2Gateway
.connect(alice)
["withdrawERC20(address,uint256,uint256)"](l2Token.address, amount, layer2GasLimit)
: await l2Gateway
.connect(alice)
["withdrawERC20(address,address,uint256,uint256)"](
l2Token.address,
recipient.address,
amount,
layer2GasLimit
);
await withdrawTx.wait();
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const balanceAfter = await l2Token.balanceOf(alice.address);
// should emit WithdrawERC20
await expect(withdrawTx)
.to.emit(l2Gateway, "WithdrawERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount, "0x");
// should emit SentMessage
const messageData = l1Gateway.interface.encodeFunctionData("finalizeWithdrawERC20", [
l1Token.address,
l2Token.address,
alice.address,
recipient.address,
amount,
"0x",
]);
await expect(withdrawTx)
.to.emit(l2Messenger, "SentMessage")
.withArgs(l1Gateway.address, l2Gateway.address, 0, 0, deadline, messageData, nonce, layer2GasLimit);
// should transfer from alice
expect(balanceBefore.sub(balanceAfter)).to.eq(amount);
// 3. relay in layer 1
const relayTx = await l1Messenger.relayMessageWithProof(
l2Gateway.address,
l1Gateway.address,
0,
0,
deadline,
nonce,
messageData,
{ batchIndex: 0, blockHeight: 0, merkleProof: "0x" }
);
await relayTx.wait();
// should emit RelayedMessage
await expect(relayTx).to.emit(l1Messenger, "RelayedMessage");
// should emit FinalizeWithdrawERC20
await expect(relayTx)
.to.emit(l1Gateway, "FinalizeWithdrawERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount, "0x");
// should transfer out
expect(await l1Token.balanceOf(l1Gateway.address)).to.eq(0);
expect(await l1Token.balanceOf(recipient.address)).to.eq(amount);
});
it("should succeed, when transfer with data", async () => {
const calldata = "0x3d4233433232";
// 1. approve
await l2Token.connect(alice).approve(l2Gateway.address, amount);
// 2. withdraw
const nonce = await l2Messenger.messageNonce();
const withdrawTx = await l2Gateway
.connect(alice)
.withdrawERC20AndCall(l2Token.address, recipient.address, amount, calldata, layer2GasLimit);
await withdrawTx.wait();
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
// should emit WithdrawERC20
await expect(withdrawTx)
.to.emit(l2Gateway, "WithdrawERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount, calldata);
// should emit SentMessage
const messageData = l1Gateway.interface.encodeFunctionData("finalizeWithdrawERC20", [
l1Token.address,
l2Token.address,
alice.address,
recipient.address,
amount,
calldata,
]);
await expect(withdrawTx)
.to.emit(l2Messenger, "SentMessage")
.withArgs(l1Gateway.address, l2Gateway.address, 0, 0, deadline, messageData, nonce, layer2GasLimit);
// 3. relay in layer 1
const relayTx = await l1Messenger.relayMessageWithProof(
l2Gateway.address,
l1Gateway.address,
0,
0,
deadline,
nonce,
messageData,
{ batchIndex: 0, blockHeight: 0, merkleProof: "0x" }
);
await relayTx.wait();
// should emit RelayedMessage
await expect(relayTx).to.emit(l1Messenger, "RelayedMessage");
// should emit FinalizeWithdrawERC20
await expect(relayTx)
.to.emit(l1Gateway, "FinalizeWithdrawERC20")
.withArgs(l1Token.address, l2Token.address, alice.address, recipient.address, amount, calldata);
// should transfer out
expect(await l1Token.balanceOf(l1Gateway.address)).to.eq(0);
expect(await l1Token.balanceOf(recipient.address)).to.eq(amount);
});
});
};
for (const decimals of [6, 18, 24]) {
for (const sendToSelf of [true, false]) {
run1to2(decimals, sendToSelf);
run2to1(decimals, sendToSelf);
}
}
});
context("WETHGateway", async () => {
let l1Gateway: L1WETHGateway;
let l2Gateway: L2WETHGateway;
let l1WETH: WETH9;
let l2WETH: WETH9;
beforeEach(async () => {
// deploy weth in layer 1 and layer 2
const WETH9 = await ethers.getContractFactory("WETH9", deployer);
l1WETH = await WETH9.deploy();
l2WETH = await WETH9.deploy();
// deploy gateway in layer 1
const L1WETHGateway = await ethers.getContractFactory("L1WETHGateway", deployer);
l1Gateway = await L1WETHGateway.deploy();
// deploy gateway in layer 2
const L2WETHGateway = await ethers.getContractFactory("L2WETHGateway", deployer);
l2Gateway = await L2WETHGateway.deploy();
// initialize gateway in layer 1
await l1Gateway.initialize(
l2Gateway.address,
router.address,
l1Messenger.address,
l1WETH.address,
l2WETH.address
);
// initialize gateway in layer 2
await l2Gateway.initialize(
l1Gateway.address,
router.address,
l2Messenger.address,
l2WETH.address,
l1WETH.address
);
});
const run1to2 = async (sendToSelf: boolean) => {
context(`layer 1 to layer 2: sendToSelf[${sendToSelf}]`, async () => {
const amount = ethers.utils.parseEther("100");
let recipient: SignerWithAddress;
beforeEach(async () => {
recipient = sendToSelf ? alice : bob;
if ((await ethers.provider.getBalance(l2Messenger.address)).eq(constants.Zero)) {
await deployer.sendTransaction({ to: l2Messenger.address, value: amount });
await l1WETH.connect(alice).deposit({ value: amount });
}
expect(await ethers.provider.getBalance(l2Messenger.address)).to.eq(amount);
});
it("should transfer to layer 2 without data", async () => {
// 1. deposit and approve
await l1WETH.connect(alice).approve(l1Gateway.address, amount);
// 2. do deposit
const nonce = await rollup.getQeueuLength();
const beforeBalanceLayer1 = await ethers.provider.getBalance(l1Messenger.address);
const depositTx = sendToSelf
? await l1Gateway
.connect(alice)
["depositERC20(address,uint256,uint256)"](l1WETH.address, amount, layer1GasLimit)
: await l1Gateway
.connect(alice)
["depositERC20(address,address,uint256,uint256)"](
l1WETH.address,
recipient.address,
amount,
layer1GasLimit
);
await depositTx.wait();
const afterBalanceLayer1 = await ethers.provider.getBalance(l1Messenger.address);
// should emit DepositERC20
await expect(depositTx)
.to.emit(l1Gateway, "DepositERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, "0x");
// should emit SentMessage
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l2Gateway.interface.encodeFunctionData("finalizeDepositERC20", [
l1WETH.address,
l2WETH.address,
alice.address,
recipient.address,
amount,
"0x",
]);
await expect(depositTx)
.to.emit(l1Messenger, "SentMessage")
.withArgs(l2Gateway.address, l1Gateway.address, amount, 0, deadline, messageData, nonce, layer1GasLimit);
// should unwrap transfer to messenger
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount);
// 3. do relay in layer 2
const beforeBalanceLayer2 = await l2WETH.balanceOf(recipient.address);
const relayTx = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
amount,
0,
deadline,
nonce,
messageData
);
await relayTx.wait();
const afterBalanceLayer2 = await l2WETH.balanceOf(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l2Messenger, "RelayedMessage");
// should emit FinalizeDepositERC20
await expect(relayTx)
.to.emit(l2Gateway, "FinalizeDepositERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, "0x");
// should transfer and wrap weth in layer 2
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount);
expect(await ethers.provider.getBalance(l2Messenger.address)).to.eq(constants.Zero);
});
it("should transfer to layer 2 data", async () => {
const calldata = "0x3333444555fdad";
// 1. deposit and approve
await l1WETH.connect(alice).approve(l1Gateway.address, amount);
// 2. do deposit
const nonce = await rollup.getQeueuLength();
const beforeBalanceLayer1 = await ethers.provider.getBalance(l1Messenger.address);
const depositTx = await l1Gateway
.connect(alice)
.depositERC20AndCall(l1WETH.address, recipient.address, amount, calldata, layer1GasLimit);
await depositTx.wait();
const afterBalanceLayer1 = await ethers.provider.getBalance(l1Messenger.address);
// should emit DepositERC20
await expect(depositTx)
.to.emit(l1Gateway, "DepositERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, calldata);
// should emit SentMessage
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l2Gateway.interface.encodeFunctionData("finalizeDepositERC20", [
l1WETH.address,
l2WETH.address,
alice.address,
recipient.address,
amount,
calldata,
]);
await expect(depositTx)
.to.emit(l1Messenger, "SentMessage")
.withArgs(l2Gateway.address, l1Gateway.address, amount, 0, deadline, messageData, nonce, layer1GasLimit);
// should unwrap transfer to messenger
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount);
// 3. do relay in layer 2
const beforeBalanceLayer2 = await l2WETH.balanceOf(recipient.address);
const relayTx = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
amount,
0,
deadline,
nonce,
messageData
);
await relayTx.wait();
const afterBalanceLayer2 = await l2WETH.balanceOf(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l2Messenger, "RelayedMessage");
// should emit FinalizeDepositERC20
await expect(relayTx)
.to.emit(l2Gateway, "FinalizeDepositERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, calldata);
// should transfer and wrap weth in layer 2
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount);
expect(await ethers.provider.getBalance(l2Messenger.address)).to.eq(constants.Zero);
});
});
};
const run2to1 = async (sendToSelf: boolean) => {
context(`layer 2 to layer 1: sendToSelf[${sendToSelf}]`, async () => {
const amount = ethers.utils.parseEther("100");
let recipient: SignerWithAddress;
beforeEach(async () => {
recipient = sendToSelf ? alice : bob;
await l1WETH.connect(alice).deposit({ value: amount });
await l1WETH.connect(alice).approve(l1Gateway.address, amount);
await l1Gateway.connect(alice)["depositERC20(address,uint256,uint256)"](l1WETH.address, amount, 0);
await l2WETH.connect(alice).deposit({ value: amount });
});
it("should transfer to layer 1 without data", async () => {
// 1. approve
await l2WETH.connect(alice).approve(l2Gateway.address, amount);
// 2. do withdraw in layer 2
const nonce = await l2Messenger.messageNonce();
const beforeBalanceLayer2 = await ethers.provider.getBalance(l2Messenger.address);
const withdrawTx = sendToSelf
? await l2Gateway
.connect(alice)
["withdrawERC20(address,uint256,uint256)"](l2WETH.address, amount, layer2GasLimit)
: await l2Gateway
.connect(alice)
["withdrawERC20(address,address,uint256,uint256)"](
l2WETH.address,
recipient.address,
amount,
layer2GasLimit
);
await withdrawTx.wait();
const afterBalanceLayer2 = await ethers.provider.getBalance(l2Messenger.address);
// should emit WithdrawERC20
await expect(withdrawTx)
.to.emit(l2Gateway, "WithdrawERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, "0x");
// should emit SentMessage
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l1Gateway.interface.encodeFunctionData("finalizeWithdrawERC20", [
l1WETH.address,
l2WETH.address,
alice.address,
recipient.address,
amount,
"0x",
]);
await expect(withdrawTx)
.to.emit(l2Messenger, "SentMessage")
.withArgs(l1Gateway.address, l2Gateway.address, amount, 0, deadline, messageData, nonce, layer2GasLimit);
// should unwrap transfer to messenger
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount);
// 3. do relay in layer 1
const beforeBalanceLayer1 = await l1WETH.balanceOf(recipient.address);
const relayTx = await l1Messenger.relayMessageWithProof(
l2Gateway.address,
l1Gateway.address,
amount,
0,
deadline,
nonce,
messageData,
{ batchIndex: 0, blockHeight: 0, merkleProof: "0x" }
);
await relayTx.wait();
const afterBalanceLayer1 = await l1WETH.balanceOf(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l1Messenger, "RelayedMessage");
// should emit FinalizeWithdrawERC20
await expect(relayTx)
.to.emit(l1Gateway, "FinalizeWithdrawERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, "0x");
// should transfer and wrap weth in layer 1
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount);
});
it("should transfer to layer 1 with data", async () => {
const calldata = "0x33445566778899";
// 1. approve
await l2WETH.connect(alice).approve(l2Gateway.address, amount);
// 2. do withdraw in layer 2
const nonce = await l2Messenger.messageNonce();
const beforeBalanceLayer2 = await ethers.provider.getBalance(l2Messenger.address);
const withdrawTx = await l2Gateway
.connect(alice)
.withdrawERC20AndCall(l2WETH.address, recipient.address, amount, calldata, layer2GasLimit);
await withdrawTx.wait();
const afterBalanceLayer2 = await ethers.provider.getBalance(l2Messenger.address);
// should emit WithdrawERC20
await expect(withdrawTx)
.to.emit(l2Gateway, "WithdrawERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, calldata);
// should emit SentMessage
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l1Gateway.interface.encodeFunctionData("finalizeWithdrawERC20", [
l1WETH.address,
l2WETH.address,
alice.address,
recipient.address,
amount,
calldata,
]);
await expect(withdrawTx)
.to.emit(l2Messenger, "SentMessage")
.withArgs(l1Gateway.address, l2Gateway.address, amount, 0, deadline, messageData, nonce, layer2GasLimit);
// should unwrap transfer to messenger
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount);
// 3. do relay in layer 1
const beforeBalanceLayer1 = await l1WETH.balanceOf(recipient.address);
const relayTx = await l1Messenger.relayMessageWithProof(
l2Gateway.address,
l1Gateway.address,
amount,
0,
deadline,
nonce,
messageData,
{ batchIndex: 0, blockHeight: 0, merkleProof: "0x" }
);
await relayTx.wait();
const afterBalanceLayer1 = await l1WETH.balanceOf(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l1Messenger, "RelayedMessage");
// should emit FinalizeWithdrawERC20
await expect(relayTx)
.to.emit(l1Gateway, "FinalizeWithdrawERC20")
.withArgs(l1WETH.address, l2WETH.address, alice.address, recipient.address, amount, calldata);
// should transfer and wrap weth in layer 1
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount);
});
});
};
for (const sendToSelf of [true, false]) {
run1to2(sendToSelf);
run2to1(sendToSelf);
}
});
});

View File

@@ -1,220 +0,0 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { constants } from "ethers";
import { keccak256 } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { ZKRollup, L1ScrollMessenger, L2ScrollMessenger, L1GatewayRouter, L2GatewayRouter } from "../typechain";
describe("GatewayRouter", async () => {
const layer1GasLimit = 12345;
const layer2GasLimit = 54321;
const DROP_DELAY_DURATION = 86400 * 7;
let deployer: SignerWithAddress;
let alice: SignerWithAddress;
let bob: SignerWithAddress;
let rollup: ZKRollup;
let l1Messenger: L1ScrollMessenger;
let l2Messenger: L2ScrollMessenger;
beforeEach(async () => {
[deployer, alice, bob] = await ethers.getSigners();
const RollupVerifier = await ethers.getContractFactory("RollupVerifier", deployer);
const verifier = await RollupVerifier.deploy();
await verifier.deployed();
// deploy ZKRollup in layer 1
const ZKRollup = await ethers.getContractFactory("ZKRollup", {
signer: deployer,
libraries: { RollupVerifier: verifier.address },
});
rollup = (await ZKRollup.deploy()) as ZKRollup;
await rollup.initialize(233);
await rollup.importGenesisBlock({
blockHash: keccak256(constants.HashZero),
parentHash: constants.HashZero,
baseFee: 0,
stateRoot: constants.HashZero,
blockHeight: 0,
gasUsed: 0,
timestamp: 0,
extraData: "0x",
txs: []
});
// deploy L1ScrollMessenger in layer 1
const L1ScrollMessenger = await ethers.getContractFactory("L1ScrollMessenger", deployer);
l1Messenger = await L1ScrollMessenger.deploy();
await l1Messenger.initialize(rollup.address);
await rollup.updateMessenger(l1Messenger.address);
// deploy L2ScrollMessenger in layer 2
const L2ScrollMessenger = await ethers.getContractFactory("L2ScrollMessenger", deployer);
l2Messenger = await L2ScrollMessenger.deploy(deployer.address);
});
context("WETHGateway", async () => {
let l1Gateway: L1GatewayRouter;
let l2Gateway: L2GatewayRouter;
beforeEach(async () => {
// deploy gateway in layer 1
const L1GatewayRouter = await ethers.getContractFactory("L1GatewayRouter", deployer);
l1Gateway = await L1GatewayRouter.deploy();
// deploy gateway in layer 2
const L2GatewayRouter = await ethers.getContractFactory("L2GatewayRouter", deployer);
l2Gateway = await L2GatewayRouter.deploy();
// initialize gateway in layer 1
await l1Gateway.initialize(constants.AddressZero, l2Gateway.address, l1Messenger.address);
// initialize gateway in layer 2
await l2Gateway.initialize(constants.AddressZero, l1Gateway.address, l2Messenger.address);
});
const run1to2 = async (sendToSelf: boolean) => {
context(`layer 1 to layer 2: sendToSelf[${sendToSelf}]`, async () => {
const amount = ethers.utils.parseEther("100");
let recipient: SignerWithAddress;
beforeEach(async () => {
recipient = sendToSelf ? alice : bob;
if ((await ethers.provider.getBalance(l2Messenger.address)).eq(constants.Zero)) {
await deployer.sendTransaction({ to: l2Messenger.address, value: amount });
}
expect(await ethers.provider.getBalance(l2Messenger.address)).to.eq(amount);
});
it("should transfer to layer 2 without data", async () => {
// 2. do deposit
const nonce = await rollup.getQeueuLength();
const beforeBalanceLayer1 = await ethers.provider.getBalance(l1Messenger.address);
const depositTx = sendToSelf
? await l1Gateway.connect(alice)["depositETH(uint256)"](layer1GasLimit, { value: amount })
: await l1Gateway
.connect(alice)
["depositETH(address,uint256)"](recipient.address, layer1GasLimit, { value: amount });
await depositTx.wait();
const afterBalanceLayer1 = await ethers.provider.getBalance(l1Messenger.address);
// should emit DepositETH
await expect(depositTx)
.to.emit(l1Gateway, "DepositETH")
.withArgs(alice.address, recipient.address, amount, "0x");
// should emit SentMessage
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l2Gateway.interface.encodeFunctionData("finalizeDepositETH", [
alice.address,
recipient.address,
amount,
"0x",
]);
await expect(depositTx)
.to.emit(l1Messenger, "SentMessage")
.withArgs(l2Gateway.address, l1Gateway.address, amount, 0, deadline, messageData, nonce, layer1GasLimit);
// should unwrap transfer to messenger
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount);
// 3. do relay in layer 2
const beforeBalanceLayer2 = await ethers.provider.getBalance(recipient.address);
const relayTx = await l2Messenger.relayMessage(
l1Gateway.address,
l2Gateway.address,
amount,
0,
deadline,
nonce,
messageData
);
await relayTx.wait();
const afterBalanceLayer2 = await ethers.provider.getBalance(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l2Messenger, "RelayedMessage");
// should emit FinalizeDepositETH
await expect(relayTx)
.to.emit(l2Gateway, "FinalizeDepositETH")
.withArgs(alice.address, recipient.address, amount, "0x");
// should transfer and wrap weth in layer 2
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount);
expect(await ethers.provider.getBalance(l2Messenger.address)).to.eq(constants.Zero);
});
});
};
const run2to1 = async (sendToSelf: boolean) => {
context(`layer 2 to layer 1: sendToSelf[${sendToSelf}]`, async () => {
const amount = ethers.utils.parseEther("100");
let recipient: SignerWithAddress;
beforeEach(async () => {
recipient = sendToSelf ? alice : bob;
await l1Gateway["depositETH(uint256)"](layer1GasLimit, { value: amount });
});
it("should transfer to layer 1 without data", async () => {
// 2. do withdraw in layer 2
const nonce = await l2Messenger.messageNonce();
const beforeBalanceLayer2 = await ethers.provider.getBalance(l2Messenger.address);
const withdrawTx = sendToSelf
? await l2Gateway.connect(alice)["withdrawETH(uint256)"](layer2GasLimit, { value: amount })
: await l2Gateway
.connect(alice)
["withdrawETH(address,uint256)"](recipient.address, layer2GasLimit, { value: amount });
await withdrawTx.wait();
const afterBalanceLayer2 = await ethers.provider.getBalance(l2Messenger.address);
// should emit WithdrawETH
await expect(withdrawTx)
.to.emit(l2Gateway, "WithdrawETH")
.withArgs(alice.address, recipient.address, amount, "0x");
// should emit SentMessage
const deadline = (await ethers.provider.getBlock("latest")).timestamp + DROP_DELAY_DURATION;
const messageData = l1Gateway.interface.encodeFunctionData("finalizeWithdrawETH", [
alice.address,
recipient.address,
amount,
"0x",
]);
await expect(withdrawTx)
.to.emit(l2Messenger, "SentMessage")
.withArgs(l1Gateway.address, l2Gateway.address, amount, 0, deadline, messageData, nonce, layer2GasLimit);
// should unwrap transfer to messenger
expect(afterBalanceLayer2.sub(beforeBalanceLayer2)).to.eq(amount);
// 3. do relay in layer 1
const beforeBalanceLayer1 = await ethers.provider.getBalance(recipient.address);
const relayTx = await l1Messenger.relayMessageWithProof(
l2Gateway.address,
l1Gateway.address,
amount,
0,
deadline,
nonce,
messageData,
{ batchIndex: 0, blockHeight: 0, merkleProof: "0x" }
);
await relayTx.wait();
const afterBalanceLayer1 = await ethers.provider.getBalance(recipient.address);
// should emit RelayedMessage
await expect(relayTx).to.emit(l1Messenger, "RelayedMessage");
// should emit FinalizeWithdrawETH
await expect(relayTx)
.to.emit(l1Gateway, "FinalizeWithdrawETH")
.withArgs(alice.address, recipient.address, amount, "0x");
// should transfer and wrap weth in layer 1
expect(afterBalanceLayer1.sub(beforeBalanceLayer1)).to.eq(amount);
});
});
};
for (const sendToSelf of [true, false]) {
run1to2(sendToSelf);
run2to1(sendToSelf);
}
});
});

View File

@@ -0,0 +1,230 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { expect } from "chai";
import { BigNumber, BigNumberish, constants } from "ethers";
import { concat, RLP } from "ethers/lib/utils";
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 RLP.encode([
test.parentHash,
test.uncleHash,
test.coinbase,
test.stateRoot,
test.transactionsRoot,
test.receiptsRoot,
test.logsBloom,
BigNumber.from(test.difficulty).isZero() ? "0x" : BigNumber.from(test.difficulty).toHexString(),
BigNumber.from(test.blockHeight).toHexString(),
BigNumber.from(test.gasLimit).toHexString(),
BigNumber.from(test.gasUsed).toHexString(),
BigNumber.from(test.blockTimestamp).toHexString(),
test.extraData,
test.mixHash,
test.blockNonce,
BigNumber.from(test.baseFee).toHexString(),
]);
}
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);
});
it("should revert, when sender not allowed", async () => {
const [deployer] = await ethers.getSigners();
await container.initialize(
test.parentHash,
test.blockHeight - 1,
test.blockTimestamp - 1,
test.baseFee,
test.stateRoot
);
const Whitelist = await ethers.getContractFactory("Whitelist", deployer);
const whitelist = await Whitelist.deploy(deployer.address);
await container.updateWhitelist(whitelist.address);
await expect(container.importBlockHeader(constants.HashZero, [], 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(
constants.HashZero,
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

@@ -0,0 +1,120 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { expect } from "chai";
import { concat } from "ethers/lib/utils";
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",
],
},
];
describe("PatriciaMerkleTrieVerifier", async () => {
let verifier: MockPatriciaMerkleTrieVerifier;
beforeEach(async () => {
const [deployer] = await ethers.getSigners();
const MockPatriciaMerkleTrieVerifier = await ethers.getContractFactory("MockPatriciaMerkleTrieVerifier", deployer);
verifier = await MockPatriciaMerkleTrieVerifier.deploy();
await verifier.deployed();
});
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

@@ -0,0 +1,107 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { constants } from "ethers";
import { concat } from "ethers/lib/utils";
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 L1MessageQueue = await ethers.getContractFactory("L1MessageQueue", deployer);
queue = await L1MessageQueue.deploy();
await queue.deployed();
const RollupVerifier = await ethers.getContractFactory("RollupVerifier", deployer);
const verifier = await RollupVerifier.deploy();
await verifier.deployed();
const ScrollChain = await ethers.getContractFactory("ScrollChain", {
signer: deployer,
libraries: { RollupVerifier: verifier.address },
});
chain = await ScrollChain.deploy(0, 25, "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6");
await chain.deployed();
await chain.initialize(queue.address);
await chain.updateSequencer(deployer.address, true);
await queue.initialize(constants.AddressZero, constants.AddressZero);
});
it("should succeed", async () => {
await chain.importGenesisBatch({
blocks: [
{
blockHash: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
parentHash: constants.HashZero,
blockNumber: 0,
timestamp: 0,
baseFee: 0,
gasLimit: 0,
numTransactions: 0,
numL1Messages: 0,
},
],
prevStateRoot: constants.HashZero,
newStateRoot: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
withdrawTrieRoot: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
batchIndex: 0,
parentBatchHash: constants.HashZero,
l2Transactions: [],
});
const parentBatchHash = await chain.lastFinalizedBatchHash();
for (let numTx = 1; numTx <= 25; ++numTx) {
for (let txLength = 100; 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 batch = {
blocks: [
{
blockHash: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
parentHash: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
blockNumber: 1,
timestamp: numTx * 100000 + txLength,
baseFee: 0,
gasLimit: 0,
numTransactions: 0,
numL1Messages: 0,
},
],
prevStateRoot: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
newStateRoot: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
withdrawTrieRoot: "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6",
batchIndex: 1,
parentBatchHash: parentBatchHash,
l2Transactions: concat(txs),
};
const estimateGas = await chain.estimateGas.commitBatch(batch);
const tx = await chain.commitBatch(batch, { gasLimit: estimateGas.mul(12).div(10) });
const receipt = await tx.wait();
console.log(
"Commit batch with l2TransactionsBytes:",
numTx * (txLength + 4),
"gasLimit:",
tx.gasLimit.toString(),
"estimateGas:",
estimateGas.toString(),
"gasUsed:",
receipt.gasUsed.toString()
);
}
}
});
});

View File

@@ -11,13 +11,15 @@ 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_zkrollup.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
@@ -28,11 +30,13 @@ env CONTRACT_NAME=L2StandardERC20Gateway npx hardhat run --network $layer2 scrip
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
# initalize 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_zkrollup.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

View File

@@ -1,48 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
if (!addressFile.get("L1StandardERC20Gateway.implementation")) {
console.log(">> Deploy L1StandardERC20Gateway implementation");
const L1StandardERC20Gateway = await ethers.getContractFactory("L1StandardERC20Gateway", deployer);
const impl = await L1StandardERC20Gateway.deploy();
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`✅ L1StandardERC20Gateway implementation deployed at ${impl.address}`);
addressFile.set("L1StandardERC20Gateway.implementation", impl.address);
}
const impl = addressFile.get("L1StandardERC20Gateway.implementation") as string;
if (!addressFile.get("L1StandardERC20Gateway.proxy")) {
console.log(">> Deploy L1StandardERC20Gateway proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`✅ L1StandardERC20Gateway proxy deployed at ${proxy.address}`);
addressFile.set("L1StandardERC20Gateway.proxy", proxy.address);
}
// Export contract address to testnet.
console.log(
`testnet-export: ${addressFile.get("L1StandardERC20Gateway.implementation")};${addressFile.get(
"L1StandardERC20Gateway.proxy"
)}`
);
}
// 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;
});

View File

@@ -1,46 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
if (!addressFile.get("L1GatewayRouter.implementation")) {
console.log(">> Deploy L1GatewayRouter implementation");
const L1GatewayRouter = await ethers.getContractFactory("L1GatewayRouter", deployer);
const impl = await L1GatewayRouter.deploy();
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`✅ L1GatewayRouter implementation deployed at ${impl.address}`);
addressFile.set("L1GatewayRouter.implementation", impl.address);
}
const impl = addressFile.get("L1GatewayRouter.implementation") as string;
if (!addressFile.get("L1GatewayRouter.proxy")) {
console.log(">> Deploy L1GatewayRouter proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`✅ L1GatewayRouter proxy deployed at ${proxy.address}`);
addressFile.set("L1GatewayRouter.proxy", proxy.address);
}
// Export contract address to testnet.
console.log(
`testnet-export: ${addressFile.get("L1GatewayRouter.implementation")};${addressFile.get("L1GatewayRouter.proxy")}`
);
}
// 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;
});

View File

@@ -1,48 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
if (!addressFile.get("L1ScrollMessenger.implementation")) {
console.log(">> Deploy L1ScrollMessenger implementation");
const L1ScrollMessenger = await ethers.getContractFactory("L1ScrollMessenger", deployer);
const impl = await L1ScrollMessenger.deploy();
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`✅ L1ScrollMessenger implementation deployed at ${impl.address}`);
addressFile.set("L1ScrollMessenger.implementation", impl.address);
}
const impl = addressFile.get("L1ScrollMessenger.implementation") as string;
if (!addressFile.get("L1ScrollMessenger.proxy")) {
console.log(">> Deploy L1ScrollMessenger proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`✅ L1ScrollMessenger proxy deployed at ${proxy.address}`);
addressFile.set("L1ScrollMessenger.proxy", proxy.address);
}
// Export contract address to testnet.
console.log(
`testnet-export: ${addressFile.get("L1ScrollMessenger.implementation")};${addressFile.get(
"L1ScrollMessenger.proxy"
)}`
);
}
// 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;
});

View File

@@ -1,48 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
if (!addressFile.get("L2StandardERC20Gateway.implementation")) {
console.log(">> Deploy L2StandardERC20Gateway implementation");
const L2StandardERC20Gateway = await ethers.getContractFactory("L2StandardERC20Gateway", deployer);
const impl = await L2StandardERC20Gateway.deploy();
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`✅ L2StandardERC20Gateway implementation deployed at ${impl.address}`);
addressFile.set("L2StandardERC20Gateway.implementation", impl.address);
}
const impl = addressFile.get("L2StandardERC20Gateway.implementation") as string;
if (!addressFile.get("L2StandardERC20Gateway.proxy")) {
console.log(">> Deploy L2StandardERC20Gateway proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`✅ L2StandardERC20Gateway proxy deployed at ${proxy.address}`);
addressFile.set("L2StandardERC20Gateway.proxy", proxy.address);
}
// Export contract address to testnet.
console.log(
`testnet-export: ${addressFile.get("L2StandardERC20Gateway.implementation")};${addressFile.get(
"L2StandardERC20Gateway.proxy"
)}`
);
}
// 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;
});

View File

@@ -1,46 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
if (!addressFile.get("L2GatewayRouter.implementation")) {
console.log(">> Deploy L2GatewayRouter implementation");
const L2GatewayRouter = await ethers.getContractFactory("L2GatewayRouter", deployer);
const impl = await L2GatewayRouter.deploy();
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`✅ L2GatewayRouter implementation deployed at ${impl.address}`);
addressFile.set("L2GatewayRouter.implementation", impl.address);
}
const impl = addressFile.get("L2GatewayRouter.implementation") as string;
if (!addressFile.get("L2GatewayRouter.proxy")) {
console.log(">> Deploy L2GatewayRouter proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`✅ L2GatewayRouter proxy deployed at ${proxy.address}`);
addressFile.set("L2GatewayRouter.proxy", proxy.address);
}
// Export contract address to testnet.
console.log(
`testnet-export: ${addressFile.get("L2GatewayRouter.implementation")};${addressFile.get("L2GatewayRouter.proxy")}`
);
}
// 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;
});

View File

@@ -8,19 +8,38 @@ async function main() {
const [deployer] = await ethers.getSigners();
const owner = process.env.CONTRACT_OWNER || deployer.address;
if (!addressFile.get("L2ScrollMessenger")) {
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
const container = process.env.L1_BLOCK_CONTAINER_ADDR!;
const queue = process.env.L2_MESSAGE_QUEUE_ADDR!;
if (!addressFile.get("L2ScrollMessenger.implementation")) {
console.log(">> Deploy L2ScrollMessenger implementation");
const L2ScrollMessenger = await ethers.getContractFactory("L2ScrollMessenger", deployer);
const impl = await L2ScrollMessenger.deploy(owner);
const impl = await L2ScrollMessenger.deploy(container, queue);
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`✅ L2ScrollMessenger implementation deployed at ${impl.address}`);
addressFile.set("L2ScrollMessenger", impl.address);
addressFile.set("L2ScrollMessenger.implementation", impl.address);
}
const impl = addressFile.get("L2ScrollMessenger.implementation") as string;
if (!addressFile.get("L2ScrollMessenger.proxy")) {
console.log(">> Deploy L2ScrollMessenger proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`✅ L2ScrollMessenger proxy deployed at ${proxy.address}`);
addressFile.set(`L2ScrollMessenger.proxy`, proxy.address);
}
// Export contract address to testnet.
console.log(`testnet-export: ${addressFile.get("L2ScrollMessenger")}`);
console.log(
`testnet-export: ${addressFile.get("L2ScrollMessenger.implementation")};${addressFile.get(
"L2ScrollMessenger.proxy"
)}`
);
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -8,47 +8,54 @@ async function main() {
const [deployer] = await ethers.getSigners();
const CHAIN_ID_L2 = process.env.CHAIN_ID_L2 || "none";
const MAX_TX_IN_BATCH = process.env.MAX_TX_IN_BATCH || 25;
const PADDING_TX_HASH =
process.env.PADDING_TX_HASH || "0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6";
const ProxyAdmin = await ethers.getContractAt("ProxyAdmin", addressFile.get("ProxyAdmin"), deployer);
if (!addressFile.get("ZKRollup.verifier")) {
if (!addressFile.get("ScrollChain.verifier")) {
console.log(">> Deploy RollupVerifier");
const RollupVerifier = await ethers.getContractFactory("RollupVerifier", deployer);
const verifier = await RollupVerifier.deploy();
console.log(`>> waiting for transaction: ${verifier.deployTransaction.hash}`);
await verifier.deployed();
console.log(`✅ RollupVerifier deployed at ${verifier.address}`);
addressFile.set("ZKRollup.verifier", verifier.address);
addressFile.set("ScrollChain.verifier", verifier.address);
}
if (!addressFile.get("ZKRollup.implementation")) {
console.log(">> Deploy ZKRollup implementation");
const ZKRollup = await ethers.getContractFactory("ZKRollup", {
if (!addressFile.get("ScrollChain.implementation")) {
console.log(">> Deploy ScrollChain implementation");
const ScrollChain = await ethers.getContractFactory("ScrollChain", {
libraries: {
RollupVerifier: addressFile.get("ZKRollup.verifier"),
RollupVerifier: addressFile.get("ScrollChain.verifier"),
},
signer: deployer,
});
const impl = await ZKRollup.deploy();
const impl = await ScrollChain.deploy(CHAIN_ID_L2, MAX_TX_IN_BATCH, PADDING_TX_HASH);
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`ZKRollup implementation deployed at ${impl.address}`);
addressFile.set("ZKRollup.implementation", impl.address);
console.log(`ScrollChain implementation deployed at ${impl.address}`);
addressFile.set("ScrollChain.implementation", impl.address);
}
const impl = addressFile.get("ZKRollup.implementation") as string;
const impl = addressFile.get("ScrollChain.implementation") as string;
if (!addressFile.get("ZKRollup.proxy")) {
console.log(">> Deploy ZKRollup proxy");
if (!addressFile.get("ScrollChain.proxy")) {
console.log(">> Deploy ScrollChain proxy");
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const proxy = await TransparentUpgradeableProxy.deploy(impl, ProxyAdmin.address, "0x");
console.log(`>> waiting for transaction: ${proxy.deployTransaction.hash}`);
await proxy.deployed();
console.log(`ZKRollup proxy deployed at ${proxy.address}`);
addressFile.set("ZKRollup.proxy", proxy.address);
console.log(`ScrollChain proxy deployed at ${proxy.address}`);
addressFile.set("ScrollChain.proxy", proxy.address);
}
// Export contract address to testnet.
console.log(`testnet-export: ${addressFile.get("ZKRollup.implementation")};${addressFile.get("ZKRollup.proxy")}`);
console.log(
`testnet-export: ${addressFile.get("ScrollChain.implementation")};${addressFile.get("ScrollChain.proxy")}`
);
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -2,7 +2,7 @@
pragma solidity ^0.8.10;
import { Script } from "forge-std/Script.sol";
import { console} from "forge-std/console.sol";
import { console } from "forge-std/console.sol";
import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
@@ -10,96 +10,198 @@ import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/trans
import { L1CustomERC20Gateway } from "../../src/L1/gateways/L1CustomERC20Gateway.sol";
import { L1ERC1155Gateway } from "../../src/L1/gateways/L1ERC1155Gateway.sol";
import { L1ERC721Gateway } from "../../src/L1/gateways/L1ERC721Gateway.sol";
import { L1ETHGateway } from "../../src/L1/gateways/L1ETHGateway.sol";
import { L1GatewayRouter } from "../../src/L1/gateways/L1GatewayRouter.sol";
import { L1ScrollMessenger } from "../../src/L1/L1ScrollMessenger.sol";
import { L1StandardERC20Gateway } from "../../src/L1/gateways/L1StandardERC20Gateway.sol";
import { L1WETHGateway } from "../../src/L1/gateways/L1WETHGateway.sol";
import { RollupVerifier } from "../../src/libraries/verifier/RollupVerifier.sol";
import { ZKRollup } from "../../src/L1/rollup/ZKRollup.sol";
import { L1MessageQueue } from "../../src/L1/rollup/L1MessageQueue.sol";
import { L2GasPriceOracle } from "../../src/L1/rollup/L2GasPriceOracle.sol";
import { ScrollChain } from "../../src/L1/rollup/ScrollChain.sol";
import { Whitelist } from "../../src/L2/predeploys/Whitelist.sol";
contract DeployL1BridgeContracts is Script {
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
ProxyAdmin proxyAdmin;
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
function run() external {
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
uint256 CHAIN_ID_L2 = vm.envUint("CHAIN_ID_L2");
// note: the RollupVerifier library is deployed implicitly
uint256 MAX_TX_IN_ONE_BATCH = vm.envOr("MAX_TX_IN_ONE_BATCH", uint256(25));
deployProxyAdmin();
deployZKRollup();
deployL1StandardERC20Gateway();
deployL1GatewayRouter();
deployL1ScrollMessenger();
deployL1CustomERC20Gateway();
deployL1ERC721Gateway();
deployL1ERC1155Gateway();
bytes32 PADDING_TX_HASH =
vm.envOr("PADDING_TX_HASH", bytes32(0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6));
vm.stopBroadcast();
}
address L1_WETH_ADDR = vm.envAddress("L1_WETH_ADDR");
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
function deployProxyAdmin() internal {
proxyAdmin = new ProxyAdmin();
ProxyAdmin proxyAdmin;
logAddress("L1_PROXY_ADMIN_ADDR", address(proxyAdmin));
}
function run() external {
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
function deployZKRollup() internal {
ZKRollup impl = new ZKRollup();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
// note: the RollupVerifier library is deployed implicitly
logAddress("L1_ZK_ROLLUP_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ZK_ROLLUP_PROXY_ADDR", address(proxy));
}
deployProxyAdmin();
deployL1Whitelist();
deployL1MessageQueue();
deployL2GasPriceOracle();
deployScrollChain();
deployL1ETHGateway();
deployL1WETHGateway();
deployL1StandardERC20Gateway();
deployL1GatewayRouter();
deployL1ScrollMessenger();
deployL1CustomERC20Gateway();
deployL1ERC721Gateway();
deployL1ERC1155Gateway();
function deployL1StandardERC20Gateway() internal {
L1StandardERC20Gateway impl = new L1StandardERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
vm.stopBroadcast();
}
logAddress("L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployProxyAdmin() internal {
proxyAdmin = new ProxyAdmin();
function deployL1GatewayRouter() internal {
L1GatewayRouter impl = new L1GatewayRouter();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
logAddress("L1_PROXY_ADMIN_ADDR", address(proxyAdmin));
}
logAddress("L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_GATEWAY_ROUTER_PROXY_ADDR", address(proxy));
}
function deployL1Whitelist() internal {
address owner = vm.addr(L1_DEPLOYER_PRIVATE_KEY);
Whitelist whitelist = new Whitelist(owner);
function deployL1ScrollMessenger() internal {
L1ScrollMessenger impl = new L1ScrollMessenger();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
logAddress("L1_WHITELIST_ADDR", address(whitelist));
}
logAddress("L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
}
function deployScrollChain() internal {
ScrollChain impl = new ScrollChain(CHAIN_ID_L2, MAX_TX_IN_ONE_BATCH, PADDING_TX_HASH);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
function deployL1CustomERC20Gateway() internal {
L1CustomERC20Gateway impl = new L1CustomERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
logAddress("L1_ZK_ROLLUP_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ZK_ROLLUP_PROXY_ADDR", address(proxy));
}
logAddress("L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1MessageQueue() internal {
L1MessageQueue impl = new L1MessageQueue();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_MESSAGE_QUEUE_PROXY_ADDR", address(proxy));
}
function deployL1ERC721Gateway() internal {
L1ERC721Gateway impl = new L1ERC721Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
function deployL2GasPriceOracle() internal {
L2GasPriceOracle impl = new L2GasPriceOracle();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_GAS_PRICE_ORACLE_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_GAS_PRICE_ORACLE_PROXY_ADDR", address(proxy));
}
logAddress("L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ERC721_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1StandardERC20Gateway() internal {
L1StandardERC20Gateway impl = new L1StandardERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
function deployL1ERC1155Gateway() internal {
L1ERC1155Gateway impl = new L1ERC1155Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
logAddress("L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
logAddress("L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ERC1155_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1ETHGateway() internal {
L1ETHGateway impl = new L1ETHGateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
function logAddress(string memory name, address addr) internal {
console.log(string(abi.encodePacked(name, "=", vm.toString(address(addr)))));
}
logAddress("L1_ETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ETH_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1WETHGateway() internal {
L1WETHGateway impl = new L1WETHGateway(L1_WETH_ADDR, L2_WETH_ADDR);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_WETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_WETH_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1GatewayRouter() internal {
L1GatewayRouter impl = new L1GatewayRouter();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_GATEWAY_ROUTER_PROXY_ADDR", address(proxy));
}
function deployL1ScrollMessenger() internal {
L1ScrollMessenger impl = new L1ScrollMessenger();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
}
function deployL1CustomERC20Gateway() internal {
L1CustomERC20Gateway impl = new L1CustomERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1ERC721Gateway() internal {
L1ERC721Gateway impl = new L1ERC721Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ERC721_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL1ERC1155Gateway() internal {
L1ERC1155Gateway impl = new L1ERC1155Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L1_ERC1155_GATEWAY_PROXY_ADDR", address(proxy));
}
function logAddress(string memory name, address addr) internal view {
console.log(string(abi.encodePacked(name, "=", vm.toString(address(addr)))));
}
}

View File

@@ -2,7 +2,7 @@
pragma solidity ^0.8.10;
import { Script } from "forge-std/Script.sol";
import { console} from "forge-std/console.sol";
import { console } from "forge-std/console.sol";
import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
@@ -10,93 +10,237 @@ import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/trans
import { L2CustomERC20Gateway } from "../../src/L2/gateways/L2CustomERC20Gateway.sol";
import { L2ERC1155Gateway } from "../../src/L2/gateways/L2ERC1155Gateway.sol";
import { L2ERC721Gateway } from "../../src/L2/gateways/L2ERC721Gateway.sol";
import { L2ETHGateway } from "../../src/L2/gateways/L2ETHGateway.sol";
import { L2GatewayRouter } from "../../src/L2/gateways/L2GatewayRouter.sol";
import { L2ScrollMessenger } from "../../src/L2/L2ScrollMessenger.sol";
import { L2StandardERC20Gateway } from "../../src/L2/gateways/L2StandardERC20Gateway.sol";
import { L2WETHGateway } from "../../src/L2/gateways/L2WETHGateway.sol";
import { L1BlockContainer } from "../../src/L2/predeploys/L1BlockContainer.sol";
import { L1GasPriceOracle } from "../../src/L2/predeploys/L1GasPriceOracle.sol";
import { L2MessageQueue } from "../../src/L2/predeploys/L2MessageQueue.sol";
import { L2TxFeeVault } from "../../src/L2/predeploys/L2TxFeeVault.sol";
import { Whitelist } from "../../src/L2/predeploys/Whitelist.sol";
import { ScrollStandardERC20 } from "../../src/libraries/token/ScrollStandardERC20.sol";
import { ScrollStandardERC20Factory } from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
contract DeployL2BridgeContracts is Script {
uint256 L2_DEPLOYER_PRIVATE_KEY = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
ProxyAdmin proxyAdmin;
uint256 L2_DEPLOYER_PRIVATE_KEY = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
function run() external {
vm.startBroadcast(L2_DEPLOYER_PRIVATE_KEY);
address L1_TX_FEE_RECIPIENT_ADDR = vm.envAddress("L1_TX_FEE_RECIPIENT_ADDR");
address L1_WETH_ADDR = vm.envAddress("L1_WETH_ADDR");
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
deployL2ScrollMessenger();
deployProxyAdmin();
deployL2StandardERC20Gateway();
deployL2GatewayRouter();
deployScrollStandardERC20Factory();
deployL2CustomERC20Gateway();
deployL2ERC721Gateway();
deployL2ERC1155Gateway();
L1GasPriceOracle oracle;
L1BlockContainer container;
L2MessageQueue queue;
ProxyAdmin proxyAdmin;
vm.stopBroadcast();
// predeploy contracts
address L1_BLOCK_CONTAINER_PREDEPLOY_ADDR = vm.envOr("L1_BLOCK_CONTAINER_PREDEPLOY_ADDR", address(0));
address L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR = vm.envOr("L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR", address(0));
address L2_MESSAGE_QUEUE_PREDEPLOY_ADDR = vm.envOr("L2_MESSAGE_QUEUE_PREDEPLOY_ADDR", address(0));
address L2_TX_FEE_VAULT_PREDEPLOY_ADDR = vm.envOr("L2_TX_FEE_VAULT_PREDEPLOY_ADDR", address(0));
address L2_WHITELIST_PREDEPLOY_ADDR = vm.envOr("L2_WHITELIST_PREDEPLOY_ADDR", address(0));
function run() external {
vm.startBroadcast(L2_DEPLOYER_PRIVATE_KEY);
// predeploys
deployL1GasPriceOracle();
deployL1BlockContainer();
deployL2MessageQueue();
deployTxFeeVault();
deployL2Whitelist();
// upgradable
deployProxyAdmin();
deployL2ScrollMessenger();
deployL2ETHGateway();
deployL2WETHGateway();
deployL2StandardERC20Gateway();
deployL2GatewayRouter();
deployScrollStandardERC20Factory();
deployL2CustomERC20Gateway();
deployL2ERC721Gateway();
deployL2ERC1155Gateway();
vm.stopBroadcast();
}
function deployL1GasPriceOracle() internal {
if (L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR != address(0)) {
oracle = L1GasPriceOracle(L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR);
logAddress("L1_GAS_PRICE_ORACLE_ADDR", address(L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR));
return;
}
function deployL2ScrollMessenger() internal {
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
L2ScrollMessenger l2ScrollMessenger = new L2ScrollMessenger(owner);
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
oracle = new L1GasPriceOracle(owner);
logAddress("L2_SCROLL_MESSENGER_ADDR", address(l2ScrollMessenger));
logAddress("L1_GAS_PRICE_ORACLE_ADDR", address(oracle));
}
function deployL1BlockContainer() internal {
if (L1_BLOCK_CONTAINER_PREDEPLOY_ADDR != address(0)) {
container = L1BlockContainer(L1_BLOCK_CONTAINER_PREDEPLOY_ADDR);
logAddress("L1_BLOCK_CONTAINER_ADDR", address(L1_BLOCK_CONTAINER_PREDEPLOY_ADDR));
return;
}
function deployProxyAdmin() internal {
proxyAdmin = new ProxyAdmin();
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
container = new L1BlockContainer(owner);
logAddress("L2_PROXY_ADMIN_ADDR", address(proxyAdmin));
logAddress("L1_BLOCK_CONTAINER_ADDR", address(container));
}
function deployL2MessageQueue() internal {
if (L2_MESSAGE_QUEUE_PREDEPLOY_ADDR != address(0)) {
queue = L2MessageQueue(L2_MESSAGE_QUEUE_PREDEPLOY_ADDR);
logAddress("L2_MESSAGE_QUEUE_ADDR", address(L2_MESSAGE_QUEUE_PREDEPLOY_ADDR));
return;
}
function deployL2StandardERC20Gateway() internal {
L2StandardERC20Gateway impl = new L2StandardERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
queue = new L2MessageQueue(owner);
logAddress("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
logAddress("L2_MESSAGE_QUEUE_ADDR", address(queue));
}
function deployTxFeeVault() internal {
if (L2_TX_FEE_VAULT_PREDEPLOY_ADDR != address(0)) {
logAddress("L2_TX_FEE_VAULT_ADDR", address(L2_TX_FEE_VAULT_PREDEPLOY_ADDR));
return;
}
function deployL2GatewayRouter() internal {
L2GatewayRouter impl = new L2GatewayRouter();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
L2TxFeeVault feeVault = new L2TxFeeVault(address(owner), L1_TX_FEE_RECIPIENT_ADDR);
logAddress("L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_GATEWAY_ROUTER_PROXY_ADDR", address(proxy));
logAddress("L2_TX_FEE_VAULT_ADDR", address(feeVault));
}
function deployL2Whitelist() internal {
if (L2_WHITELIST_PREDEPLOY_ADDR != address(0)) {
logAddress("L2_WHITELIST_ADDR", address(L2_WHITELIST_PREDEPLOY_ADDR));
return;
}
function deployScrollStandardERC20Factory() internal {
ScrollStandardERC20 tokenImpl = new ScrollStandardERC20();
ScrollStandardERC20Factory scrollStandardERC20Factory = new ScrollStandardERC20Factory(address(tokenImpl));
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
Whitelist whitelist = new Whitelist(owner);
logAddress("L2_SCROLL_STANDARD_ERC20_ADDR", address(tokenImpl));
logAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR", address(scrollStandardERC20Factory));
}
logAddress("L2_WHITELIST_ADDR", address(whitelist));
}
function deployL2CustomERC20Gateway() internal {
L2CustomERC20Gateway impl = new L2CustomERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
function deployProxyAdmin() internal {
proxyAdmin = new ProxyAdmin();
logAddress("L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
logAddress("L2_PROXY_ADMIN_ADDR", address(proxyAdmin));
}
function deployL2ERC721Gateway() internal {
L2ERC721Gateway impl = new L2ERC721Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
function deployL2ScrollMessenger() internal {
L2ScrollMessenger impl = new L2ScrollMessenger(address(container), address(oracle), address(queue));
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_ERC721_GATEWAY_PROXY_ADDR", address(proxy));
}
logAddress("L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
}
function deployL2ERC1155Gateway() internal {
L2ERC1155Gateway impl = new L2ERC1155Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(impl), address(proxyAdmin), new bytes(0));
function deployL2StandardERC20Gateway() internal {
L2StandardERC20Gateway impl = new L2StandardERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_ERC1155_GATEWAY_PROXY_ADDR", address(proxy));
}
logAddress("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
function logAddress(string memory name, address addr) internal {
console.log(string(abi.encodePacked(name, "=", vm.toString(address(addr)))));
}
function deployL2ETHGateway() internal {
L2ETHGateway impl = new L2ETHGateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_ETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_ETH_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL2WETHGateway() internal {
L2WETHGateway impl = new L2WETHGateway(L2_WETH_ADDR, L1_WETH_ADDR);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_WETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_WETH_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL2GatewayRouter() internal {
L2GatewayRouter impl = new L2GatewayRouter();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_GATEWAY_ROUTER_PROXY_ADDR", address(proxy));
}
function deployScrollStandardERC20Factory() internal {
ScrollStandardERC20 tokenImpl = new ScrollStandardERC20();
ScrollStandardERC20Factory scrollStandardERC20Factory = new ScrollStandardERC20Factory(address(tokenImpl));
logAddress("L2_SCROLL_STANDARD_ERC20_ADDR", address(tokenImpl));
logAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR", address(scrollStandardERC20Factory));
}
function deployL2CustomERC20Gateway() internal {
L2CustomERC20Gateway impl = new L2CustomERC20Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL2ERC721Gateway() internal {
L2ERC721Gateway impl = new L2ERC721Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_ERC721_GATEWAY_PROXY_ADDR", address(proxy));
}
function deployL2ERC1155Gateway() internal {
L2ERC1155Gateway impl = new L2ERC1155Gateway();
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),
new bytes(0)
);
logAddress("L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
logAddress("L2_ERC1155_GATEWAY_PROXY_ADDR", address(proxy));
}
function logAddress(string memory name, address addr) internal view {
console.log(string(abi.encodePacked(name, "=", vm.toString(address(addr)))));
}
}

View File

@@ -6,81 +6,121 @@ import { Script } from "forge-std/Script.sol";
import { L1CustomERC20Gateway } from "../../src/L1/gateways/L1CustomERC20Gateway.sol";
import { L1ERC1155Gateway } from "../../src/L1/gateways/L1ERC1155Gateway.sol";
import { L1ERC721Gateway } from "../../src/L1/gateways/L1ERC721Gateway.sol";
import { L1ETHGateway } from "../../src/L1/gateways/L1ETHGateway.sol";
import { L1GatewayRouter } from "../../src/L1/gateways/L1GatewayRouter.sol";
import { L1ScrollMessenger } from "../../src/L1/L1ScrollMessenger.sol";
import { L1StandardERC20Gateway } from "../../src/L1/gateways/L1StandardERC20Gateway.sol";
import { ZKRollup } from "../../src/L1/rollup/ZKRollup.sol";
import { L1WETHGateway } from "../../src/L1/gateways/L1WETHGateway.sol";
import { ScrollChain } from "../../src/L1/rollup/ScrollChain.sol";
import { L1MessageQueue } from "../../src/L1/rollup/L1MessageQueue.sol";
import { L2GasPriceOracle } from "../../src/L1/rollup/L2GasPriceOracle.sol";
contract InitializeL1BridgeContracts is Script {
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
uint256 CHAIN_ID_L2 = vm.envUint("CHAIN_ID_L2");
address L1_ROLLUP_OPERATOR_ADDR = vm.envAddress("L1_ROLLUP_OPERATOR_ADDR");
uint256 CHAIN_ID_L2 = vm.envUint("CHAIN_ID_L2");
address L1_ROLLUP_OPERATOR_ADDR = vm.envAddress("L1_ROLLUP_OPERATOR_ADDR");
address L1_ZK_ROLLUP_PROXY_ADDR = vm.envAddress("L1_ZK_ROLLUP_PROXY_ADDR");
address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L1_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L1_GATEWAY_ROUTER_PROXY_ADDR");
address L1_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L1_SCROLL_MESSENGER_PROXY_ADDR");
address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L1_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC721_GATEWAY_PROXY_ADDR");
address L1_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC1155_GATEWAY_PROXY_ADDR");
address L1_FEE_VAULT_ADDR = vm.envAddress("L1_FEE_VAULT_ADDR");
address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L2_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L2_GATEWAY_ROUTER_PROXY_ADDR");
address L2_SCROLL_STANDARD_ERC20_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_ADDR");
address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR");
address L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L2_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC721_GATEWAY_PROXY_ADDR");
address L2_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC1155_GATEWAY_PROXY_ADDR");
address L1_WHITELIST_ADDR = vm.envAddress("L1_WHITELIST_ADDR");
address L1_ZK_ROLLUP_PROXY_ADDR = vm.envAddress("L1_ZK_ROLLUP_PROXY_ADDR");
address L1_MESSAGE_QUEUE_PROXY_ADDR = vm.envAddress("L1_MESSAGE_QUEUE_PROXY_ADDR");
address L2_GAS_PRICE_ORACLE_PROXY_ADDR = vm.envAddress("L2_GAS_PRICE_ORACLE_PROXY_ADDR");
address L1_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L1_SCROLL_MESSENGER_PROXY_ADDR");
address L1_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L1_GATEWAY_ROUTER_PROXY_ADDR");
address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L1_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC721_GATEWAY_PROXY_ADDR");
address L1_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC1155_GATEWAY_PROXY_ADDR");
address L1_ETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ETH_GATEWAY_PROXY_ADDR");
address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L1_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_WETH_GATEWAY_PROXY_ADDR");
function run() external {
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
address L2_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_PROXY_ADDR");
address L2_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L2_GATEWAY_ROUTER_PROXY_ADDR");
address L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L2_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC721_GATEWAY_PROXY_ADDR");
address L2_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC1155_GATEWAY_PROXY_ADDR");
address L2_ETH_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ETH_GATEWAY_PROXY_ADDR");
address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L2_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L2_WETH_GATEWAY_PROXY_ADDR");
address L2_SCROLL_STANDARD_ERC20_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_ADDR");
address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR");
// initialize L1StandardERC20Gateway
L1StandardERC20Gateway(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize(
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR,
L2_SCROLL_STANDARD_ERC20_ADDR,
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR
);
function run() external {
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
// initialize L1GatewayRouter
L1GatewayRouter(L1_GATEWAY_ROUTER_PROXY_ADDR).initialize(
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize ScrollChain
ScrollChain(L1_ZK_ROLLUP_PROXY_ADDR).initialize(L1_MESSAGE_QUEUE_PROXY_ADDR);
ScrollChain(L1_ZK_ROLLUP_PROXY_ADDR).updateSequencer(L1_ROLLUP_OPERATOR_ADDR, true);
// initialize ZKRollup
ZKRollup(L1_ZK_ROLLUP_PROXY_ADDR).initialize(CHAIN_ID_L2);
ZKRollup(L1_ZK_ROLLUP_PROXY_ADDR).updateMessenger(L1_SCROLL_MESSENGER_PROXY_ADDR);
ZKRollup(L1_ZK_ROLLUP_PROXY_ADDR).updateOperator(L1_ROLLUP_OPERATOR_ADDR);
// initialize L2GasPriceOracle
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).initialize();
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).updateWhitelist(L1_WHITELIST_ADDR);
// initialize L1ScrollMessenger
L1ScrollMessenger(payable(L1_SCROLL_MESSENGER_PROXY_ADDR)).initialize(
L1_ZK_ROLLUP_PROXY_ADDR
);
// initialize L1MessageQueue
L1MessageQueue(L1_MESSAGE_QUEUE_PROXY_ADDR).initialize(
L1_SCROLL_MESSENGER_PROXY_ADDR,
L2_GAS_PRICE_ORACLE_PROXY_ADDR
);
// initialize L1CustomERC20Gateway
L1CustomERC20Gateway(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize(
L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L1ScrollMessenger
L1ScrollMessenger(payable(L1_SCROLL_MESSENGER_PROXY_ADDR)).initialize(
L2_SCROLL_MESSENGER_PROXY_ADDR,
L1_FEE_VAULT_ADDR,
L1_ZK_ROLLUP_PROXY_ADDR,
L1_MESSAGE_QUEUE_PROXY_ADDR
);
L1ScrollMessenger(payable(L1_SCROLL_MESSENGER_PROXY_ADDR)).updateWhitelist(L1_WHITELIST_ADDR);
// initialize L1ERC1155Gateway
L1ERC1155Gateway(L1_ERC1155_GATEWAY_PROXY_ADDR).initialize(
L2_ERC1155_GATEWAY_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L1GatewayRouter
L1GatewayRouter(L1_GATEWAY_ROUTER_PROXY_ADDR).initialize(
L1_ETH_GATEWAY_PROXY_ADDR,
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR
);
// initialize L1ERC721Gateway
L1ERC721Gateway(L1_ERC721_GATEWAY_PROXY_ADDR).initialize(
L2_ERC721_GATEWAY_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L1CustomERC20Gateway
L1CustomERC20Gateway(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize(
L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
vm.stopBroadcast();
}
// initialize L1ERC1155Gateway
L1ERC1155Gateway(L1_ERC1155_GATEWAY_PROXY_ADDR).initialize(
L2_ERC1155_GATEWAY_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L1ERC721Gateway
L1ERC721Gateway(L1_ERC721_GATEWAY_PROXY_ADDR).initialize(
L2_ERC721_GATEWAY_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L1ETHGateway
L1ETHGateway(L1_ETH_GATEWAY_PROXY_ADDR).initialize(
L2_ETH_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L1StandardERC20Gateway
L1StandardERC20Gateway(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize(
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR,
L2_SCROLL_STANDARD_ERC20_ADDR,
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR
);
// initialize L1WETHGateway
L1WETHGateway(payable(L1_WETH_GATEWAY_PROXY_ADDR)).initialize(
L2_WETH_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L1_SCROLL_MESSENGER_PROXY_ADDR
);
vm.stopBroadcast();
}
}

View File

@@ -3,72 +3,124 @@ pragma solidity ^0.8.10;
import { Script } from "forge-std/Script.sol";
import { L2ScrollMessenger } from "../../src/L2/L2ScrollMessenger.sol";
import { L2CustomERC20Gateway } from "../../src/L2/gateways/L2CustomERC20Gateway.sol";
import { L2ERC1155Gateway } from "../../src/L2/gateways/L2ERC1155Gateway.sol";
import { L2ERC721Gateway } from "../../src/L2/gateways/L2ERC721Gateway.sol";
import { L2ETHGateway } from "../../src/L2/gateways/L2ETHGateway.sol";
import { L2GatewayRouter } from "../../src/L2/gateways/L2GatewayRouter.sol";
import { L2StandardERC20Gateway } from "../../src/L2/gateways/L2StandardERC20Gateway.sol";
import { L2WETHGateway } from "../../src/L2/gateways/L2WETHGateway.sol";
import { L2MessageQueue } from "../../src/L2/predeploys/L2MessageQueue.sol";
import { L2TxFeeVault } from "../../src/L2/predeploys/L2TxFeeVault.sol";
import { L1BlockContainer } from "../../src/L2/predeploys/L1BlockContainer.sol";
import { L1GasPriceOracle } from "../../src/L2/predeploys/L1GasPriceOracle.sol";
import { Whitelist } from "../../src/L2/predeploys/Whitelist.sol";
import { ScrollStandardERC20Factory } from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
contract InitializeL2BridgeContracts is Script {
uint256 deployerPrivateKey = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
uint256 deployerPrivateKey = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L1_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L1_GATEWAY_ROUTER_PROXY_ADDR");
address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L1_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC721_GATEWAY_PROXY_ADDR");
address L1_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC1155_GATEWAY_PROXY_ADDR");
address L1_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L1_SCROLL_MESSENGER_PROXY_ADDR");
address L1_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L1_GATEWAY_ROUTER_PROXY_ADDR");
address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L1_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC721_GATEWAY_PROXY_ADDR");
address L1_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC1155_GATEWAY_PROXY_ADDR");
address L1_ETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ETH_GATEWAY_PROXY_ADDR");
address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L1_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_WETH_GATEWAY_PROXY_ADDR");
address L2_SCROLL_MESSENGER_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_ADDR");
address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L2_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L2_GATEWAY_ROUTER_PROXY_ADDR");
address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR");
address L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L2_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC721_GATEWAY_PROXY_ADDR");
address L2_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC1155_GATEWAY_PROXY_ADDR");
address L2_TX_FEE_VAULT_ADDR = vm.envAddress("L2_TX_FEE_VAULT_ADDR");
address L1_BLOCK_CONTAINER_ADDR = vm.envAddress("L1_BLOCK_CONTAINER_ADDR");
address L1_GAS_PRICE_ORACLE_ADDR = vm.envAddress("L1_GAS_PRICE_ORACLE_ADDR");
address L2_WHITELIST_ADDR = vm.envAddress("L2_WHITELIST_ADDR");
address L2_MESSAGE_QUEUE_ADDR = vm.envAddress("L2_MESSAGE_QUEUE_ADDR");
function run() external {
vm.startBroadcast(deployerPrivateKey);
address L2_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_PROXY_ADDR");
address L2_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L2_GATEWAY_ROUTER_PROXY_ADDR");
address L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
address L2_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC721_GATEWAY_PROXY_ADDR");
address L2_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC1155_GATEWAY_PROXY_ADDR");
address L2_ETH_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ETH_GATEWAY_PROXY_ADDR");
address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
address L2_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L2_WETH_GATEWAY_PROXY_ADDR");
address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR");
// initialize L2StandardERC20Gateway
L2StandardERC20Gateway(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize(
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_ADDR,
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR
);
function run() external {
vm.startBroadcast(deployerPrivateKey);
// initialize L2GatewayRouter
L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).initialize(
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
L1_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_ADDR
);
// initialize L2MessageQueue
L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).initialize();
L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).updateMessenger(L2_SCROLL_MESSENGER_PROXY_ADDR);
// initialize ScrollStandardERC20Factory
ScrollStandardERC20Factory(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR).transferOwnership(
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR
);
// initialize L2TxFeeVault
L2TxFeeVault(payable(L2_TX_FEE_VAULT_ADDR)).updateMessenger(L2_SCROLL_MESSENGER_PROXY_ADDR);
// initialize L2CustomERC20Gateway
L2CustomERC20Gateway(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize(
L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_ADDR
);
// initialize L1BlockContainer
L1BlockContainer(L1_BLOCK_CONTAINER_ADDR).updateWhitelist(L2_WHITELIST_ADDR);
// initialize L2ERC1155Gateway
L2ERC1155Gateway(L2_ERC1155_GATEWAY_PROXY_ADDR).initialize(
L1_ERC1155_GATEWAY_PROXY_ADDR,
L2_SCROLL_MESSENGER_ADDR
);
// initialize L1GasPriceOracle
L1GasPriceOracle(L1_GAS_PRICE_ORACLE_ADDR).updateWhitelist(L2_WHITELIST_ADDR);
// initialize L2ERC721Gateway
L2ERC721Gateway(L2_ERC721_GATEWAY_PROXY_ADDR).initialize(
L1_ERC721_GATEWAY_PROXY_ADDR,
L2_SCROLL_MESSENGER_ADDR
);
// initialize L2ScrollMessenger
L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).initialize(
L1_SCROLL_MESSENGER_PROXY_ADDR,
L2_TX_FEE_VAULT_ADDR
);
L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).updateWhitelist(L2_WHITELIST_ADDR);
vm.stopBroadcast();
}
// initialize L2GatewayRouter
L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).initialize(
L2_ETH_GATEWAY_PROXY_ADDR,
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR
);
// initialize L2CustomERC20Gateway
L2CustomERC20Gateway(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR).initialize(
L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L2ERC1155Gateway
L2ERC1155Gateway(L2_ERC1155_GATEWAY_PROXY_ADDR).initialize(
L1_ERC1155_GATEWAY_PROXY_ADDR,
L2_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L2ERC721Gateway
L2ERC721Gateway(L2_ERC721_GATEWAY_PROXY_ADDR).initialize(
L1_ERC721_GATEWAY_PROXY_ADDR,
L2_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L2ETHGateway
L2ETHGateway(L2_ETH_GATEWAY_PROXY_ADDR).initialize(
L1_ETH_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize L2StandardERC20Gateway
L2StandardERC20Gateway(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR).initialize(
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_PROXY_ADDR,
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR
);
// initialize L2WETHGateway
L2WETHGateway(payable(L2_WETH_GATEWAY_PROXY_ADDR)).initialize(
L1_WETH_GATEWAY_PROXY_ADDR,
L2_GATEWAY_ROUTER_PROXY_ADDR,
L2_SCROLL_MESSENGER_PROXY_ADDR
);
// initialize ScrollStandardERC20Factory
ScrollStandardERC20Factory(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR).transferOwnership(
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR
);
vm.stopBroadcast();
}
}

View File

@@ -15,16 +15,16 @@ async function main() {
const [deployer] = await ethers.getSigners();
const rollupAddr = process.env.L1_ZK_ROLLUP_PROXY_ADDR || addressFile.get("ZKRollup.proxy") || "0x";
const rollupAddr = process.env.L1_ZK_ROLLUP_PROXY_ADDR || addressFile.get("ScrollChain.proxy") || "0x";
console.log("Using rollup proxy address:", rollupAddr);
const ZKRollup = await ethers.getContractAt("ZKRollup", rollupAddr, deployer);
const ScrollChain = await ethers.getContractAt("ScrollChain", rollupAddr, deployer);
const genesis = JSON.parse(fs.readFileSync(GENESIS_FILE_PATH, 'utf8'));
console.log("Using genesis block:", genesis.blockHash);
const tx = await ZKRollup.importGenesisBlock(genesis);
const tx = await ScrollChain.importGenesisBatch(genesis);
console.log("importGenesisBlock ZKRollup, hash:", tx.hash);
console.log("importGenesisBatch ScrollChain, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}

View File

@@ -1,44 +1,34 @@
/* eslint-disable node/no-missing-import */
import * as dotenv from "dotenv"
import * as dotenv from "dotenv";
import { constants } from "ethers";
import * as hre from "hardhat"
import { ethers } from "hardhat"
import { selectAddressFile } from "./utils"
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
dotenv.config();
const CHAIN_ID_L2 = process.env.CHAIN_ID_L2 || "none";
const L1_MESSAGE_QUEUE = process.env.L1_MESSAGE_QUEUE || "none";
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const ZKRollup = await ethers.getContractAt("ZKRollup", addressFile.get("ZKRollup.proxy"), deployer);
const ScrollChain = await ethers.getContractAt("ScrollChain", addressFile.get("ScrollChain.proxy"), deployer);
// if ((await ZKRollup.owner()) === constants.AddressZero) {
{
const tx = await ZKRollup.initialize(CHAIN_ID_L2);
console.log("initialize ZKRollup, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
const L1ScrollMessengerAddress = addressFile.get("L1ScrollMessenger.proxy");
// if ((await ZKRollup.messenger()) === constants.AddressZero) {
{
const tx = await ZKRollup.updateMessenger(L1ScrollMessengerAddress);
console.log("updateMessenger ZKRollup, hash:", tx.hash);
if ((await ScrollChain.owner()) === constants.AddressZero) {
const tx = await ScrollChain.initialize(L1_MESSAGE_QUEUE);
console.log("initialize ScrollChain, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
const L1RollupOperatorAddress = process.env.L1_ROLLUP_OPERATOR_ADDR!;
// if ((await ZKRollup.operator()) === constants.AddressZero)
{
if ((await ScrollChain.isBatchFinalized(L1RollupOperatorAddress)) === false) {
console.log("L1_ROLLUP_OPERATOR_ADDR", L1RollupOperatorAddress);
const tx = await ZKRollup.updateOperator(L1RollupOperatorAddress);
console.log("updateOperator ZKRollup, hash:", tx.hash);
const tx = await ScrollChain.updateSequencer(L1RollupOperatorAddress, true);
console.log("updateOperator ScrollChain, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}

View File

@@ -5,54 +5,52 @@ pragma solidity ^0.8.0;
import { IScrollMessenger } from "../libraries/IScrollMessenger.sol";
interface IL1ScrollMessenger is IScrollMessenger {
/***********
* Structs *
***********/
struct L2MessageProof {
// @todo add more fields
uint256 batchIndex;
uint256 blockHeight;
// The hash of the batch where the message belongs to.
bytes32 batchHash;
// Concatenation of merkle proof for withdraw merkle trie.
bytes merkleProof;
}
/**************************************** Mutated Functions ****************************************/
/****************************
* Public Mutated Functions *
****************************/
/// @notice execute L2 => L1 message
/// @param _from The address of the sender of the message.
/// @param _to The address of the recipient of the message.
/// @param _value The msg.value passed to the message call.
/// @param _fee The amount of fee in ETH to charge.
/// @param _deadline The deadline of the message.
/// @param _nonce The nonce of the message to avoid replay attack.
/// @param _message The content of the message.
/// @param _proof The proof used to verify the correctness of the transaction.
/// @notice Relay a L2 => L1 message with message proof.
/// @param from The address of the sender of the message.
/// @param to The address of the recipient of the message.
/// @param value The msg.value passed to the message call.
/// @param nonce The nonce of the message to avoid replay attack.
/// @param message The content of the message.
/// @param proof The proof used to verify the correctness of the transaction.
function relayMessageWithProof(
address _from,
address _to,
uint256 _value,
uint256 _fee,
uint256 _deadline,
uint256 _nonce,
bytes memory _message,
L2MessageProof memory _proof
address from,
address to,
uint256 value,
uint256 nonce,
bytes memory message,
L2MessageProof memory proof
) external;
/// @notice Replay an exsisting message.
/// @param _from The address of the sender of the message.
/// @param _to The address of the recipient of the message.
/// @param _value The msg.value passed to the message call.
/// @param _fee The amount of fee in ETH to charge.
/// @param _deadline The deadline of the message.
/// @param _message The content of the message.
/// @param _queueIndex CTC Queue index for the message to replay.
/// @param _oldGasLimit Original gas limit used to send the message.
/// @param _newGasLimit New gas limit to be used for this message.
/// @param from The address of the sender of the message.
/// @param to The address of the recipient of the message.
/// @param value The msg.value passed to the message call.
/// @param queueIndex The queue index for the message to replay.
/// @param message The content of the message.
/// @param oldGasLimit Original gas limit used to send the message.
/// @param newGasLimit New gas limit to be used for this message.
function replayMessage(
address _from,
address _to,
uint256 _value,
uint256 _fee,
uint256 _deadline,
bytes memory _message,
uint256 _queueIndex,
uint32 _oldGasLimit,
uint32 _newGasLimit
address from,
address to,
uint256 value,
uint256 queueIndex,
bytes memory message,
uint32 oldGasLimit,
uint32 newGasLimit
) external;
}

View File

@@ -2,15 +2,17 @@
pragma solidity ^0.8.0;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import { IZKRollup } from "./rollup/IZKRollup.sol";
import { IL1ScrollMessenger, IScrollMessenger } from "./IL1ScrollMessenger.sol";
import { IGasOracle } from "../libraries/oracle/IGasOracle.sol";
import { ScrollConstants } from "../libraries/ScrollConstants.sol";
import { IScrollChain } from "./rollup/IScrollChain.sol";
import { IL1MessageQueue } from "./rollup/IL1MessageQueue.sol";
import { IL1ScrollMessenger } from "./IL1ScrollMessenger.sol";
import { ScrollConstants } from "../libraries/constants/ScrollConstants.sol";
import { IScrollMessenger } from "../libraries/IScrollMessenger.sol";
import { ScrollMessengerBase } from "../libraries/ScrollMessengerBase.sol";
import { ZkTrieVerifier } from "../libraries/verifier/ZkTrieVerifier.sol";
import { WithdrawTrieVerifier } from "../libraries/verifier/WithdrawTrieVerifier.sol";
// solhint-disable avoid-low-level-calls
/// @title L1ScrollMessenger
/// @notice The `L1ScrollMessenger` contract can:
@@ -22,57 +24,90 @@ import { ZkTrieVerifier } from "../libraries/verifier/ZkTrieVerifier.sol";
///
/// @dev All deposited Ether (including `WETH` deposited throng `L1WETHGateway`) will locked in
/// this contract.
contract L1ScrollMessenger is OwnableUpgradeable, PausableUpgradeable, ScrollMessengerBase, IL1ScrollMessenger {
/**************************************** Variables ****************************************/
contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1ScrollMessenger {
/*************
* Variables *
*************/
/// @notice Mapping from relay id to relay status.
mapping(bytes32 => bool) public isMessageRelayed;
mapping(bytes32 => bool) public isL1MessageRelayed;
/// @notice Mapping from message hash to drop status.
mapping(bytes32 => bool) public isMessageDropped;
/// @notice Mapping from L1 message hash to sent status.
mapping(bytes32 => bool) public isL1MessageSent;
/// @notice Mapping from message hash to execution status.
mapping(bytes32 => bool) public isMessageExecuted;
/// @notice Mapping from L2 message hash to a boolean value indicating if the message has been successfully executed.
mapping(bytes32 => bool) public isL2MessageExecuted;
/// @notice The address of Rollup contract.
address public rollup;
/**************************************** Constructor ****************************************/
/// @notice The address of L1MessageQueue contract.
address public messageQueue;
function initialize(address _rollup) public initializer {
OwnableUpgradeable.__Ownable_init();
/***************
* Constructor *
***************/
/// @notice Initialize the storage of L1ScrollMessenger.
/// @param _counterpart The address of L2ScrollMessenger contract in L2.
/// @param _feeVault The address of fee vault, which will be used to collect relayer fee.
/// @param _rollup The address of ScrollChain contract.
/// @param _messageQueue The address of L1MessageQueue contract.
function initialize(
address _counterpart,
address _feeVault,
address _rollup,
address _messageQueue
) public initializer {
PausableUpgradeable.__Pausable_init();
ScrollMessengerBase._initialize();
ScrollMessengerBase._initialize(_counterpart, _feeVault);
rollup = _rollup;
messageQueue = _messageQueue;
// initialize to a nonzero value
xDomainMessageSender = ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER;
}
/**************************************** Mutated Functions ****************************************/
/****************************
* Public Mutated Functions *
****************************/
/// @inheritdoc IScrollMessenger
function sendMessage(
address _to,
uint256 _fee,
uint256 _value,
bytes memory _message,
uint256 _gasLimit
) external payable override whenNotPaused onlyWhitelistedSender(msg.sender) {
require(msg.value >= _fee, "cannot pay fee");
) external payable override whenNotPaused {
address _messageQueue = messageQueue; // gas saving
address _counterpart = counterpart; // gas saving
// solhint-disable-next-line not-rely-on-time
uint256 _deadline = block.timestamp + dropDelayDuration;
// compute minimum fee required by GasOracle contract.
uint256 _minFee = gasOracle == address(0) ? 0 : IGasOracle(gasOracle).estimateMessageFee(msg.sender, _to, _message);
require(_fee >= _minFee, "fee too small");
uint256 _value;
unchecked {
_value = msg.value - _fee;
// compute the actual cross domain message calldata.
uint256 _messageNonce = IL1MessageQueue(_messageQueue).nextCrossDomainMessageIndex();
bytes memory _xDomainCalldata = _encodeXDomainCalldata(msg.sender, _to, _value, _messageNonce, _message);
// compute and deduct the messaging fee to fee vault.
uint256 _fee = IL1MessageQueue(_messageQueue).estimateCrossDomainMessageFee(
address(this),
_counterpart,
_xDomainCalldata,
_gasLimit
);
require(msg.value >= _fee + _value, "Insufficient msg.value");
if (_fee > 0) {
(bool _success, ) = feeVault.call{ value: _fee }("");
require(_success, "Failed to deduct the fee");
}
uint256 _nonce = IZKRollup(rollup).appendMessage(msg.sender, _to, _value, _fee, _deadline, _message, _gasLimit);
// append message to L1MessageQueue
IL1MessageQueue(_messageQueue).appendCrossDomainMessage(_counterpart, _gasLimit, _xDomainCalldata);
emit SentMessage(_to, msg.sender, _value, _fee, _deadline, _message, _nonce, _gasLimit);
// record the message hash for future use.
bytes32 _xDomainCalldataHash = keccak256(_xDomainCalldata);
isL1MessageSent[_xDomainCalldataHash] = true;
emit SentMessage(msg.sender, _to, _value, _messageNonce, _gasLimit, _message);
}
/// @inheritdoc IL1ScrollMessenger
@@ -80,49 +115,45 @@ contract L1ScrollMessenger is OwnableUpgradeable, PausableUpgradeable, ScrollMes
address _from,
address _to,
uint256 _value,
uint256 _fee,
uint256 _deadline,
uint256 _nonce,
bytes memory _message,
L2MessageProof memory _proof
) external override whenNotPaused onlyWhitelistedSender(msg.sender) {
require(xDomainMessageSender == ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER, "already in execution");
require(xDomainMessageSender == ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER, "Message is already in execution");
// solhint-disable-next-line not-rely-on-time
// @note disable for now since we cannot generate proof in time.
// require(_deadline >= block.timestamp, "Message expired");
bytes32 _xDomainCalldataHash = keccak256(_encodeXDomainCalldata(_from, _to, _value, _nonce, _message));
require(!isL2MessageExecuted[_xDomainCalldataHash], "Message was already successfully executed");
bytes32 _msghash = keccak256(abi.encodePacked(_from, _to, _value, _fee, _deadline, _nonce, _message));
require(!isMessageExecuted[_msghash], "Message successfully executed");
// @todo check proof
require(IZKRollup(rollup).isBlockFinalized(_proof.blockHeight), "invalid state proof");
require(ZkTrieVerifier.verifyMerkleProof(_proof.merkleProof), "invalid proof");
// @todo check `_to` address to avoid attack.
// @todo take fee and distribute to relayer later.
{
address _rollup = rollup;
require(IScrollChain(_rollup).isBatchFinalized(_proof.batchHash), "Batch is not finalized");
// @note skip verify for now
/*
bytes32 _messageRoot = IScrollChain(_rollup).getL2MessageRoot(_proof.batchHash);
require(
WithdrawTrieVerifier.verifyMerkleProof(_messageRoot, _xDomainCalldataHash, _nonce, _proof.merkleProof),
"Invalid proof"
);
*/
}
// @note This usually will never happen, just in case.
require(_from != xDomainMessageSender, "invalid message sender");
require(_from != xDomainMessageSender, "Invalid message sender");
xDomainMessageSender = _from;
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = _to.call{ value: _value }(_message);
// reset value to refund gas.
xDomainMessageSender = ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER;
if (success) {
isMessageExecuted[_msghash] = true;
emit RelayedMessage(_msghash);
isL2MessageExecuted[_xDomainCalldataHash] = true;
emit RelayedMessage(_xDomainCalldataHash);
} else {
emit FailedRelayedMessage(_msghash);
emit FailedRelayedMessage(_xDomainCalldataHash);
}
bytes32 _relayId = keccak256(abi.encodePacked(_msghash, msg.sender, block.number));
isMessageRelayed[_relayId] = true;
bytes32 _relayId = keccak256(abi.encodePacked(_xDomainCalldataHash, msg.sender, block.number));
isL1MessageRelayed[_relayId] = true;
}
/// @inheritdoc IL1ScrollMessenger
@@ -130,89 +161,21 @@ contract L1ScrollMessenger is OwnableUpgradeable, PausableUpgradeable, ScrollMes
address _from,
address _to,
uint256 _value,
uint256 _fee,
uint256 _deadline,
bytes memory _message,
uint256 _queueIndex,
bytes memory _message,
uint32 _oldGasLimit,
uint32 _newGasLimit
) external override whenNotPaused {
// @todo
}
/// @inheritdoc IScrollMessenger
function dropMessage(
address _from,
address _to,
uint256 _value,
uint256 _fee,
uint256 _deadline,
uint256 _nonce,
bytes memory _message,
uint256 _gasLimit
) external override whenNotPaused {
// solhint-disable-next-line not-rely-on-time
require(block.timestamp > _deadline, "message not expired");
// @todo The `queueIndex` is acutally updated asynchronously, it's not a good practice to compare directly.
address _rollup = rollup; // gas saving
uint256 _queueIndex = IZKRollup(_rollup).getNextQueueIndex();
require(_queueIndex <= _nonce, "message already executed");
bytes32 _expectedMessageHash = IZKRollup(_rollup).getMessageHashByIndex(_nonce);
bytes32 _messageHash = keccak256(
abi.encodePacked(_from, _to, _value, _fee, _deadline, _nonce, _message, _gasLimit)
);
require(_messageHash == _expectedMessageHash, "message hash mismatched");
require(!isMessageDropped[_messageHash], "message already dropped");
isMessageDropped[_messageHash] = true;
if (_from.code.length > 0) {
// @todo call finalizeDropMessage of `_from`
} else {
// just do simple ether refund
payable(_from).transfer(_value + _fee);
}
emit MessageDropped(_messageHash);
}
/**************************************** Restricted Functions ****************************************/
/************************
* Restricted Functions *
************************/
/// @notice Pause the contract
/// @dev This function can only called by contract owner.
function pause() external onlyOwner {
_pause();
}
/// @notice Update whitelist contract.
/// @dev This function can only called by contract owner.
/// @param _newWhitelist The address of new whitelist contract.
function updateWhitelist(address _newWhitelist) external onlyOwner {
address _oldWhitelist = whitelist;
whitelist = _newWhitelist;
emit UpdateWhitelist(_oldWhitelist, _newWhitelist);
}
/// @notice Update the address of gas oracle.
/// @dev This function can only called by contract owner.
/// @param _newGasOracle The address to update.
function updateGasOracle(address _newGasOracle) external onlyOwner {
address _oldGasOracle = gasOracle;
gasOracle = _newGasOracle;
emit UpdateGasOracle(_oldGasOracle, _newGasOracle);
}
/// @notice Update the drop delay duration.
/// @dev This function can only called by contract owner.
/// @param _newDuration The new delay duration to update.
function updateDropDelayDuration(uint256 _newDuration) external onlyOwner {
uint256 _oldDuration = dropDelayDuration;
dropDelayDuration = _newDuration;
emit UpdateDropDelayDuration(_oldDuration, _newDuration);
}
}

View File

@@ -4,7 +4,9 @@ pragma solidity ^0.8.0;
/// @title The interface for the ERC1155 cross chain gateway in layer 1.
interface IL1ERC1155Gateway {
/**************************************** Events ****************************************/
/**********
* Events *
**********/
/// @notice Emitted when the ERC1155 NFT is transfered to recipient in layer 1.
/// @param _l1Token The address of ERC1155 NFT in layer 1.
@@ -70,7 +72,9 @@ interface IL1ERC1155Gateway {
uint256[] _amounts
);
/**************************************** Mutated Funtions ****************************************/
/*************************
* Public View Functions *
*************************/
/// @notice Deposit some ERC1155 NFT to caller's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
@@ -82,7 +86,7 @@ interface IL1ERC1155Gateway {
uint256 _tokenId,
uint256 _amount,
uint256 _gasLimit
) external;
) external payable;
/// @notice Deposit some ERC1155 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
@@ -96,7 +100,7 @@ interface IL1ERC1155Gateway {
uint256 _tokenId,
uint256 _amount,
uint256 _gasLimit
) external;
) external payable;
/// @notice Deposit a list of some ERC1155 NFT to caller's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
@@ -108,7 +112,7 @@ interface IL1ERC1155Gateway {
uint256[] calldata _tokenIds,
uint256[] calldata _amounts,
uint256 _gasLimit
) external;
) external payable;
/// @notice Deposit a list of some ERC1155 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
@@ -122,7 +126,7 @@ interface IL1ERC1155Gateway {
uint256[] calldata _tokenIds,
uint256[] calldata _amounts,
uint256 _gasLimit
) external;
) external payable;
/// @notice Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient's account in layer 1.
/// The function should only be called by L1ScrollMessenger.

View File

@@ -3,33 +3,53 @@
pragma solidity ^0.8.0;
interface IL1ERC20Gateway {
/**************************************** Events ****************************************/
/**********
* Events *
**********/
/// @notice Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.
/// @param l1Token The address of the token in L1.
/// @param l2Token The address of the token in L2.
/// @param from The address of sender in L2.
/// @param to The address of recipient in L1.
/// @param amount The amount of token withdrawn from L2 to L1.
/// @param data The optional calldata passed to recipient in L1.
event FinalizeWithdrawERC20(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
address indexed l1Token,
address indexed l2Token,
address indexed from,
address to,
uint256 amount,
bytes data
);
/// @notice Emitted when someone deposit ERC20 token from L1 to L2.
/// @param l1Token The address of the token in L1.
/// @param l2Token The address of the token in L2.
/// @param from The address of sender in L1.
/// @param to The address of recipient in L2.
/// @param amount The amount of token will be deposited from L1 to L2.
/// @param data The optional calldata passed to recipient in L2.
event DepositERC20(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
address indexed l1Token,
address indexed l2Token,
address indexed from,
address to,
uint256 amount,
bytes data
);
/**************************************** View Functions ****************************************/
/*************************
* Public View Functions *
*************************/
/// @notice Return the corresponding l2 token address given l1 token address.
/// @param _l1Token The address of l1 token.
function getL2ERC20Address(address _l1Token) external view returns (address);
/**************************************** Mutated Functions ****************************************/
/****************************
* Public Mutated Functions *
****************************/
/// @notice Deposit some token to a caller's account on L2.
/// @dev Make this function payable to send relayer fee in Ether.

View File

@@ -4,7 +4,9 @@ pragma solidity ^0.8.0;
/// @title The interface for the ERC721 cross chain gateway in layer 1.
interface IL1ERC721Gateway {
/**************************************** Events ****************************************/
/**********
* Events *
**********/
/// @notice Emitted when the ERC721 NFT is transfered to recipient in layer 1.
/// @param _l1Token The address of ERC721 NFT in layer 1.
@@ -62,7 +64,9 @@ interface IL1ERC721Gateway {
uint256[] _tokenIds
);
/**************************************** Mutated Funtions ****************************************/
/****************************
* Public Mutated Functions *
****************************/
/// @notice Deposit some ERC721 NFT to caller's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
@@ -72,7 +76,7 @@ interface IL1ERC721Gateway {
address _token,
uint256 _tokenId,
uint256 _gasLimit
) external;
) external payable;
/// @notice Deposit some ERC721 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
@@ -84,7 +88,7 @@ interface IL1ERC721Gateway {
address _to,
uint256 _tokenId,
uint256 _gasLimit
) external;
) external payable;
/// @notice Deposit a list of some ERC721 NFT to caller's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
@@ -94,7 +98,7 @@ interface IL1ERC721Gateway {
address _token,
uint256[] calldata _tokenIds,
uint256 _gasLimit
) external;
) external payable;
/// @notice Deposit a list of some ERC721 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
@@ -106,7 +110,7 @@ interface IL1ERC721Gateway {
address _to,
uint256[] calldata _tokenIds,
uint256 _gasLimit
) external;
) external payable;
/// @notice Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient's account in layer 1.
/// @dev Requirements:

View File

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IL1ETHGateway {
/**********
* Events *
**********/
/// @notice Emitted when ETH is withdrawn from L2 to L1 and transfer to recipient.
/// @param from The address of sender in L2.
/// @param to The address of recipient in L1.
/// @param amount The amount of ETH withdrawn from L2 to L1.
/// @param data The optional calldata passed to recipient in L1.
event FinalizeWithdrawETH(address indexed from, address indexed to, uint256 amount, bytes data);
/// @notice Emitted when someone deposit ETH from L1 to L2.
/// @param from The address of sender in L1.
/// @param to The address of recipient in L2.
/// @param amount The amount of ETH will be deposited from L1 to L2.
/// @param data The optional calldata passed to recipient in L2.
event DepositETH(address indexed from, address indexed to, uint256 amount, bytes data);
/****************************
* Public Mutated Functions *
****************************/
/// @notice Deposit ETH to caller's account in L2.
/// @param amount The amount of ETH to be deposited.
/// @param gasLimit Gas limit required to complete the deposit on L2.
function depositETH(uint256 amount, uint256 gasLimit) external payable;
/// @notice Deposit ETH to some recipient's account in L2.
/// @param to The address of recipient's account on L2.
/// @param amount The amount of ETH to be deposited.
/// @param gasLimit Gas limit required to complete the deposit on L2.
function depositETH(
address to,
uint256 amount,
uint256 gasLimit
) external payable;
/// @notice Deposit ETH to some recipient's account in L2 and call the target contract.
/// @param to The address of recipient's account on L2.
/// @param amount The amount of ETH to be deposited.
/// @param data Optional data to forward to recipient's account.
/// @param gasLimit Gas limit required to complete the deposit on L2.
function depositETHAndCall(
address to,
uint256 amount,
bytes calldata data,
uint256 gasLimit
) external payable;
/// @notice Complete ETH withdraw from L2 to L1 and send fund to recipient's account in L1.
/// @dev This function should only be called by L1ScrollMessenger.
/// This function should also only be called by L1ETHGateway in L2.
/// @param from The address of account who withdraw ETH in L2.
/// @param to The address of recipient in L1 to receive ETH.
/// @param amount The amount of ETH to withdraw.
/// @param data Optional data to forward to recipient's account.
function finalizeWithdrawETH(
address from,
address to,
uint256 amount,
bytes calldata data
) external payable;
}

View File

@@ -2,40 +2,24 @@
pragma solidity ^0.8.0;
import { IL1ETHGateway } from "./IL1ETHGateway.sol";
import { IL1ERC20Gateway } from "./IL1ERC20Gateway.sol";
import { IScrollGateway } from "../../libraries/gateway/IScrollGateway.sol";
interface IL1GatewayRouter is IL1ETHGateway, IL1ERC20Gateway {
/**********
* Events *
**********/
interface IL1GatewayRouter is IL1ERC20Gateway, IScrollGateway {
/**************************************** Events ****************************************/
/// @notice Emitted when the address of ETH Gateway is updated.
/// @param ethGateway The address of new ETH Gateway.
event SetETHGateway(address indexed ethGateway);
event FinalizeWithdrawETH(address indexed _from, address indexed _to, uint256 _amount, bytes _data);
event DepositETH(address indexed _from, address indexed _to, uint256 _amount, bytes _data);
/// @notice Emitted when the address of default ERC20 Gateway is updated.
/// @param defaultERC20Gateway The address of new default ERC20 Gateway.
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway);
/**************************************** Mutated Functions ****************************************/
/// @notice Deposit ETH to call's account in L2.
/// @param _gasLimit Gas limit required to complete the deposit on L2.
function depositETH(uint256 _gasLimit) external payable;
/// @notice Deposit ETH to recipient's account in L2.
/// @param _to The address of recipient's account on L2.
/// @param _gasLimit Gas limit required to complete the deposit on L2.
function depositETH(address _to, uint256 _gasLimit) external payable;
// @todo add depositETHAndCall;
/// @notice Complete ETH withdraw from L2 to L1 and send fund to recipient's account in L1.
/// @dev This function should only be called by L1ScrollMessenger.
/// This function should also only be called by L2GatewayRouter in L2.
/// @param _from The address of account who withdraw ETH in L2.
/// @param _to The address of recipient in L1 to receive ETH.
/// @param _amount The amount of ETH to withdraw.
/// @param _data Optional data to forward to recipient's account.
function finalizeWithdrawETH(
address _from,
address _to,
uint256 _amount,
bytes calldata _data
) external payable;
/// @notice Emitted when the `gateway` for `token` is updated.
/// @param token The address of token updated.
/// @param gateway The corresponding address of gateway updated.
event SetERC20Gateway(address indexed token, address indexed gateway);
}

View File

@@ -6,10 +6,12 @@ import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/O
import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { IL1ERC20Gateway, L1ERC20Gateway } from "./L1ERC20Gateway.sol";
import { IL1ScrollMessenger } from "../IL1ScrollMessenger.sol";
import { IL2ERC20Gateway } from "../../L2/gateways/IL2ERC20Gateway.sol";
import { ScrollGatewayBase, IScrollGateway } from "../../libraries/gateway/ScrollGatewayBase.sol";
import { IL1ScrollMessenger } from "../IL1ScrollMessenger.sol";
import { IL1ERC20Gateway } from "./IL1ERC20Gateway.sol";
import { ScrollGatewayBase } from "../../libraries/gateway/ScrollGatewayBase.sol";
import { L1ERC20Gateway } from "./L1ERC20Gateway.sol";
/// @title L1CustomERC20Gateway
/// @notice The `L1CustomERC20Gateway` is used to deposit custom ERC20 compatible tokens in layer 1 and
@@ -19,21 +21,30 @@ import { ScrollGatewayBase, IScrollGateway } from "../../libraries/gateway/Scrol
contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20Gateway {
using SafeERC20Upgradeable for IERC20Upgradeable;
/**************************************** Events ****************************************/
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC20 token is updated.
/// @param _l1Token The address of ERC20 token in layer 1.
/// @param _l2Token The address of corresponding ERC20 token in layer 2.
event UpdateTokenMapping(address _l1Token, address _l2Token);
/**************************************** Variables ****************************************/
/*************
* Variables *
*************/
/// @notice Mapping from l1 token address to l2 token address for ERC20 token.
// solhint-disable-next-line var-name-mixedcase
mapping(address => address) public tokenMapping;
/**************************************** Constructor ****************************************/
/***************
* Constructor *
***************/
/// @notice Initialize the storage of L1CustomERC20Gateway.
/// @param _counterpart The address of L2CustomERC20Gateway in L2.
/// @param _router The address of L1GatewayRouter.
/// @param _messenger The address of L1ScrollMessenger.
function initialize(
address _counterpart,
address _router,
@@ -45,14 +56,18 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
}
/**************************************** View Functions ****************************************/
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IL1ERC20Gateway
function getL2ERC20Address(address _l1Token) public view override returns (address) {
return tokenMapping[_l1Token];
}
/**************************************** Mutate Functions ****************************************/
/****************************
* Public Mutated Functions *
****************************/
/// @inheritdoc IL1ERC20Gateway
function finalizeWithdrawERC20(
@@ -64,6 +79,7 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
bytes calldata _data
) external payable override onlyCallByCounterpart {
require(msg.value == 0, "nonzero msg.value");
require(_l2Token == tokenMapping[_l1Token], "l2 token mismatch");
// @note can possible trigger reentrant call to this contract or messenger,
// but it seems not a big problem.
@@ -74,12 +90,9 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
emit FinalizeWithdrawERC20(_l1Token, _l2Token, _from, _to, _amount, _data);
}
/// @inheritdoc IScrollGateway
function finalizeDropMessage() external payable {
// @todo finish the logic later
}
/**************************************** Restricted Functions ****************************************/
/************************
* Restricted Functions *
************************/
/// @notice Update layer 1 to layer 2 token mapping.
/// @param _l1Token The address of ERC20 token in layer 1.
@@ -92,7 +105,9 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
emit UpdateTokenMapping(_l1Token, _l2Token);
}
/**************************************** Internal Functions ****************************************/
/**********************
* Internal Functions *
**********************/
/// @inheritdoc L1ERC20Gateway
function _deposit(
@@ -135,7 +150,7 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
);
// 4. Send message to L1ScrollMessenger.
IL1ScrollMessenger(messenger).sendMessage{ value: msg.value }(counterpart, msg.value, _message, _gasLimit);
IL1ScrollMessenger(messenger).sendMessage{ value: msg.value }(counterpart, 0, _message, _gasLimit);
emit DepositERC20(_token, _l2Token, _from, _to, _amount, _data);
}

View File

@@ -6,10 +6,11 @@ import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/O
import { IERC1155Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
import { ERC1155HolderUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155HolderUpgradeable.sol";
import { IL1ERC1155Gateway } from "./IL1ERC1155Gateway.sol";
import { IL1ScrollMessenger } from "../IL1ScrollMessenger.sol";
import { IL2ERC1155Gateway } from "../../L2/gateways/IL2ERC1155Gateway.sol";
import { ScrollGatewayBase, IScrollGateway } from "../../libraries/gateway/ScrollGatewayBase.sol";
import { IL1ScrollMessenger } from "../IL1ScrollMessenger.sol";
import { IL1ERC1155Gateway } from "./IL1ERC1155Gateway.sol";
import { ScrollGatewayBase } from "../../libraries/gateway/ScrollGatewayBase.sol";
/// @title L1ERC1155Gateway
/// @notice The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT in layer 1 and
@@ -20,27 +21,37 @@ import { ScrollGatewayBase, IScrollGateway } from "../../libraries/gateway/Scrol
/// This will be changed if we have more specific scenarios.
// @todo Current implementation doesn't support calling from `L1GatewayRouter`.
contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, ScrollGatewayBase, IL1ERC1155Gateway {
/**************************************** Events ****************************************/
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC1155 token is updated.
/// @param _l1Token The address of ERC1155 token in layer 1.
/// @param _l1Token The address of corresponding ERC1155 token in layer 2.
event UpdateTokenMapping(address _l1Token, address _l2Token);
/**************************************** Variables ****************************************/
/*************
* Variables *
*************/
/// @notice Mapping from l1 token address to l2 token address for ERC1155 NFT.
// solhint-disable-next-line var-name-mixedcase
mapping(address => address) public tokenMapping;
/**************************************** Constructor ****************************************/
/***************
* Constructor *
***************/
/// @notice Initialize the storage of L1ERC1155Gateway.
/// @param _counterpart The address of L2ERC1155Gateway in L2.
/// @param _messenger The address of L1ScrollMessenger.
function initialize(address _counterpart, address _messenger) external initializer {
OwnableUpgradeable.__Ownable_init();
ScrollGatewayBase._initialize(_counterpart, address(0), _messenger);
}
/**************************************** Mutate Funtions ****************************************/
/****************************
* Public Mutated Functions *
****************************/
/// @inheritdoc IL1ERC1155Gateway
function depositERC1155(
@@ -48,7 +59,7 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
uint256 _tokenId,
uint256 _amount,
uint256 _gasLimit
) external override {
) external payable override {
_depositERC1155(_token, msg.sender, _tokenId, _amount, _gasLimit);
}
@@ -59,7 +70,7 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
uint256 _tokenId,
uint256 _amount,
uint256 _gasLimit
) external override {
) external payable override {
_depositERC1155(_token, _to, _tokenId, _amount, _gasLimit);
}
@@ -69,7 +80,7 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
uint256[] calldata _tokenIds,
uint256[] calldata _amounts,
uint256 _gasLimit
) external override {
) external payable override {
_batchDepositERC1155(_token, msg.sender, _tokenIds, _amounts, _gasLimit);
}
@@ -80,7 +91,7 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
uint256[] calldata _tokenIds,
uint256[] calldata _amounts,
uint256 _gasLimit
) external override {
) external payable override {
_batchDepositERC1155(_token, _to, _tokenIds, _amounts, _gasLimit);
}
@@ -93,6 +104,8 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
uint256 _tokenId,
uint256 _amount
) external override nonReentrant onlyCallByCounterpart {
require(_l2Token == tokenMapping[_l1Token], "l2 token mismatch");
IERC1155Upgradeable(_l1Token).safeTransferFrom(address(this), _to, _tokenId, _amount, "");
emit FinalizeWithdrawERC1155(_l1Token, _l2Token, _from, _to, _tokenId, _amount);
@@ -107,17 +120,16 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
uint256[] calldata _tokenIds,
uint256[] calldata _amounts
) external override nonReentrant onlyCallByCounterpart {
require(_l2Token == tokenMapping[_l1Token], "l2 token mismatch");
IERC1155Upgradeable(_l1Token).safeBatchTransferFrom(address(this), _to, _tokenIds, _amounts, "");
emit FinalizeBatchWithdrawERC1155(_l1Token, _l2Token, _from, _to, _tokenIds, _amounts);
}
/// @inheritdoc IScrollGateway
function finalizeDropMessage() external payable {
// @todo finish the logic later
}
/**************************************** Restricted Funtions ****************************************/
/************************
* Restricted Functions *
************************/
/// @notice Update layer 2 to layer 2 token mapping.
/// @param _l1Token The address of ERC1155 token in layer 1.
@@ -130,7 +142,9 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
emit UpdateTokenMapping(_l1Token, _l2Token);
}
/**************************************** Internal Funtions ****************************************/
/**********************
* Internal Functions *
**********************/
/// @dev Internal function to deposit ERC1155 NFT to layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
@@ -165,7 +179,7 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
);
// 3. Send message to L1ScrollMessenger.
IL1ScrollMessenger(messenger).sendMessage(counterpart, msg.value, _message, _gasLimit);
IL1ScrollMessenger(messenger).sendMessage{ value: msg.value }(counterpart, 0, _message, _gasLimit);
emit DepositERC1155(_token, _l2Token, msg.sender, _to, _tokenId, _amount);
}
@@ -208,7 +222,7 @@ contract L1ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, Scrol
);
// 3. Send message to L1ScrollMessenger.
IL1ScrollMessenger(messenger).sendMessage{ value: msg.value }(counterpart, msg.value, _message, _gasLimit);
IL1ScrollMessenger(messenger).sendMessage{ value: msg.value }(counterpart, 0, _message, _gasLimit);
emit BatchDepositERC1155(_token, _l2Token, msg.sender, _to, _tokenIds, _amounts);
}

View File

@@ -7,6 +7,10 @@ import { IL1ERC20Gateway } from "./IL1ERC20Gateway.sol";
// solhint-disable no-empty-blocks
abstract contract L1ERC20Gateway is IL1ERC20Gateway {
/****************************
* Public Mutated Functions *
****************************/
/// @inheritdoc IL1ERC20Gateway
function depositERC20(
address _token,
@@ -37,6 +41,10 @@ abstract contract L1ERC20Gateway is IL1ERC20Gateway {
_deposit(_token, _to, _amount, _data, _gasLimit);
}
/**********************
* Internal Functions *
**********************/
/// @dev Internal function to do all the deposit operations.
///
/// @param _token The token to deposit.

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