mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-14 00:18:03 -05:00
Compare commits
49 Commits
v4.3.52
...
fix-withdr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edffc64bcc | ||
|
|
acd7845383 | ||
|
|
5e2fe452d2 | ||
|
|
a5ca547961 | ||
|
|
8d034de87e | ||
|
|
9484c1c85f | ||
|
|
7011c3ee2e | ||
|
|
2f7e329aec | ||
|
|
33ec1e1dde | ||
|
|
5c1de26ccc | ||
|
|
bb1a7f6921 | ||
|
|
fef9f83788 | ||
|
|
1075d7d671 | ||
|
|
420c96d15a | ||
|
|
3f9e50052e | ||
|
|
04006b3ead | ||
|
|
7fe751f7c5 | ||
|
|
0da1355c4d | ||
|
|
9b5a7f7b62 | ||
|
|
b534aed080 | ||
|
|
1d358fa4ed | ||
|
|
ebf7a46242 | ||
|
|
cd883a36c2 | ||
|
|
f11ce33687 | ||
|
|
e00d5a9548 | ||
|
|
faec5a5e35 | ||
|
|
3a090eecdd | ||
|
|
bee9489c42 | ||
|
|
c4c68ef12d | ||
|
|
7f5c823a58 | ||
|
|
367636843f | ||
|
|
2f1abc06f6 | ||
|
|
cc5fd778c7 | ||
|
|
8587116ff8 | ||
|
|
a75813e6c1 | ||
|
|
01d35d7449 | ||
|
|
59c8470c04 | ||
|
|
5622f8f627 | ||
|
|
5936cd61d6 | ||
|
|
f031c38890 | ||
|
|
9bfefa0474 | ||
|
|
a6c72a2ce2 | ||
|
|
299f5e46fe | ||
|
|
7629f06243 | ||
|
|
5902bee340 | ||
|
|
e79900e24c | ||
|
|
0803dd97fb | ||
|
|
bdbddc38f5 | ||
|
|
f011fd5ac6 |
198
.github/workflows/docker.yml
vendored
198
.github/workflows/docker.yml
vendored
@@ -9,72 +9,66 @@ jobs:
|
||||
event_watcher:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push event_watcher docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/event_watcher.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/event-watcher:${{github.ref_name}}
|
||||
scrolltech/event-watcher:latest
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push event_watcher docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/event_watcher.Dockerfile
|
||||
push: true
|
||||
tags: scrolltech/event-watcher:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
gas_oracle:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push gas_oracle docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/gas_oracle.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/gas-oracle:${{github.ref_name}}
|
||||
scrolltech/gas-oracle:latest
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push gas_oracle docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/gas_oracle.Dockerfile
|
||||
push: true
|
||||
tags: scrolltech/gas-oracle:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
rollup_relayer:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push rollup_relayer docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/rollup_relayer.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/rollup-relayer:${{github.ref_name}}
|
||||
scrolltech/rollup-relayer:latest
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push rollup_relayer docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/rollup_relayer.Dockerfile
|
||||
push: true
|
||||
tags: scrolltech/rollup-relayer:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
bridgehistoryapi-fetcher:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -93,9 +87,7 @@ jobs:
|
||||
context: .
|
||||
file: ./build/dockerfiles/bridgehistoryapi-fetcher.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/bridgehistoryapi-fetcher:${{github.ref_name}}
|
||||
scrolltech/bridgehistoryapi-fetcher:latest
|
||||
tags: scrolltech/bridgehistoryapi-fetcher:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
bridgehistoryapi-api:
|
||||
@@ -116,54 +108,48 @@ jobs:
|
||||
context: .
|
||||
file: ./build/dockerfiles/bridgehistoryapi-api.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/bridgehistoryapi-api:${{github.ref_name}}
|
||||
scrolltech/bridgehistoryapi-api:latest
|
||||
tags: scrolltech/bridgehistoryapi-api:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
coordinator-api:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push coordinator docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/coordinator-api.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/coordinator-api:${{github.ref_name}}
|
||||
scrolltech/coordinator-api:latest
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push coordinator docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/coordinator-api.Dockerfile
|
||||
push: true
|
||||
tags: scrolltech/coordinator-api:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
coordinator-cron:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push coordinator docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/coordinator-cron.Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
scrolltech/coordinator-cron:${{github.ref_name}}
|
||||
scrolltech/coordinator-cron:latest
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push coordinator docker
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./build/dockerfiles/coordinator-cron.Dockerfile
|
||||
push: true
|
||||
tags: scrolltech/coordinator-cron:${{github.ref_name}}
|
||||
# cache-from: type=gha,scope=${{ github.workflow }}
|
||||
# cache-to: type=gha,scope=${{ github.workflow }}
|
||||
|
||||
@@ -33,7 +33,7 @@ Examples of unacceptable behavior include:
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct that could reasonably be considered inappropriate in a
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
## Directory Structure
|
||||
|
||||
<pre>
|
||||
├── <a href="./bridge-history-api/">bridge-history-api</a>: Bridge history service that collects deposit and withdraw events from both L1 and L2 chains and generates withdrawal proofs
|
||||
├── <a href="./bridge-history-api/">bridge-history-api</a>: Bridge history service that collects deposit and withdraw events from both L1 and L2 chain and generates withdrawal proofs
|
||||
├── <a href="./common/">common</a>: Common libraries and types
|
||||
├── <a href="./coordinator/">coordinator</a>: Prover coordinator service that dispatches proving tasks to provers
|
||||
├── <a href="./database">database</a>: Database client and schema definition
|
||||
|
||||
@@ -7,7 +7,7 @@ The bridge-history-api contains three distinct components
|
||||
|
||||
### bridgehistoryapi-db-cli
|
||||
|
||||
Provide init, show version, rollback, and check status services of DB
|
||||
Provide init, show version, rollback, check status services of DB
|
||||
```
|
||||
cd ./bridge-history-api
|
||||
make bridgehistoryapi-db-cli
|
||||
@@ -36,7 +36,7 @@ provides REST APIs. Please refer to the API details below.
|
||||
|
||||
1. `/api/txs`
|
||||
```
|
||||
// @Summary get all txs under the given address
|
||||
// @Summary get all txs under given address
|
||||
// @Accept plain
|
||||
// @Produce plain
|
||||
// @Param address query string true "wallet address"
|
||||
@@ -60,7 +60,7 @@ provides REST APIs. Please refer to the API details below.
|
||||
|
||||
3. `/api/l2/unclaimed/withdrawals`
|
||||
```
|
||||
// @Summary get all L2 unclaimed withdrawals under the given address
|
||||
// @Summary get all L2 unclaimed withdrawals under given address
|
||||
// @Accept plain
|
||||
// @Produce plain
|
||||
// @Param address query string true "wallet address"
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis/v8"
|
||||
@@ -54,23 +52,11 @@ func action(ctx *cli.Context) error {
|
||||
log.Error("failed to close db", "err", err)
|
||||
}
|
||||
}()
|
||||
opts := &redis.Options{
|
||||
Addr: cfg.Redis.Address,
|
||||
Username: cfg.Redis.Username,
|
||||
Password: cfg.Redis.Password,
|
||||
MinIdleConns: cfg.Redis.MinIdleConns,
|
||||
ReadTimeout: time.Duration(cfg.Redis.ReadTimeoutMs * int(time.Millisecond)),
|
||||
}
|
||||
// Production Redis service has enabled transit_encryption.
|
||||
if !cfg.Redis.Local {
|
||||
opts.TLSConfig = &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: true, //nolint:gosec
|
||||
}
|
||||
}
|
||||
log.Info("init redis client", "addr", opts.Addr, "user name", opts.Username, "is local", cfg.Redis.Local,
|
||||
"min idle connections", opts.MinIdleConns, "read timeout", opts.ReadTimeout)
|
||||
redisClient := redis.NewClient(opts)
|
||||
redisClient := redis.NewClient(&redis.Options{
|
||||
Addr: cfg.Redis.Address,
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
})
|
||||
api.InitController(db, redisClient)
|
||||
|
||||
router := gin.Default()
|
||||
|
||||
@@ -68,10 +68,19 @@ func action(ctx *cli.Context) error {
|
||||
|
||||
observability.Server(ctx, db)
|
||||
|
||||
l1MessageFetcher := fetcher.NewL1MessageFetcher(subCtx, cfg.L1, db, l1Client)
|
||||
// syncInfo is used to store the shared info between L1 fetcher and L2 fetcher, e.g., the sync height.
|
||||
syncInfo := &fetcher.SyncInfo{}
|
||||
|
||||
l1MessageFetcher, err := fetcher.NewL1MessageFetcher(subCtx, cfg.L1, db, l1Client, syncInfo)
|
||||
if err != nil {
|
||||
log.Crit("failed to create L1 cross message fetcher", "error", err)
|
||||
}
|
||||
go l1MessageFetcher.Start()
|
||||
|
||||
l2MessageFetcher := fetcher.NewL2MessageFetcher(subCtx, cfg.L2, db, l2Client)
|
||||
l2MessageFetcher, err := fetcher.NewL2MessageFetcher(subCtx, cfg.L2, db, l2Client, syncInfo)
|
||||
if err != nil {
|
||||
log.Crit("failed to create L2 cross message fetcher", "error", err)
|
||||
}
|
||||
go l2MessageFetcher.Start()
|
||||
|
||||
// Catch CTRL-C to ensure a graceful shutdown.
|
||||
|
||||
@@ -1,40 +1,37 @@
|
||||
{
|
||||
"L1": {
|
||||
"confirmation": 0,
|
||||
"endpoint": "https://rpc.ankr.com/eth",
|
||||
"startHeight": 18306000,
|
||||
"blockTime": 10,
|
||||
"fetchLimit": 30,
|
||||
"MessengerAddr": "0x6774Bcbd5ceCeF1336b5300fb5186a12DDD8b367",
|
||||
"ETHGatewayAddr": "0x7F2b8C31F88B6006c382775eea88297Ec1e3E905",
|
||||
"WETHGatewayAddr": "0x7AC440cAe8EB6328de4fA621163a792c1EA9D4fE",
|
||||
"StandardERC20GatewayAddr": "0xD8A791fE2bE73eb6E6cF1eb0cb3F36adC9B3F8f9",
|
||||
"CustomERC20GatewayAddr": "0xb2b10a289A229415a124EFDeF310C10cb004B6ff",
|
||||
"ERC721GatewayAddr": "0x6260aF48e8948617b8FA17F4e5CEa2d21D21554B",
|
||||
"ERC1155GatewayAddr": "0xb94f7F6ABcb811c5Ac709dE14E37590fcCd975B6",
|
||||
"USDCGatewayAddr": "0xf1AF3b23DE0A5Ca3CAb7261cb0061C0D779A5c7B",
|
||||
"LIDOGatewayAddr": "0x6625C6332c9F91F2D27c304E729B86db87A3f504",
|
||||
"DAIGatewayAddr": "0x67260A8B73C5B77B55c1805218A42A7A6F98F515",
|
||||
"ScrollChainAddr": "0xa13BAF47339d63B743e7Da8741db5456DAc1E556",
|
||||
"GatewayRouterAddr": "0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6",
|
||||
"MessageQueueAddr": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"
|
||||
"confirmation": 2,
|
||||
"endpoint": "L1-URL",
|
||||
"startHeight": 4038000,
|
||||
"blockTime": 12,
|
||||
"fetchLimit": 32,
|
||||
"MessengerAddr": "0x50c7d3e7f7c656493D1D76aaa1a836CedfCBB16A",
|
||||
"ETHGatewayAddr": "0x8A54A2347Da2562917304141ab67324615e9866d",
|
||||
"WETHGatewayAddr": "0x3dA0BF44814cfC678376b3311838272158211695",
|
||||
"StandardERC20GatewayAddr": "0x65D123d6389b900d954677c26327bfc1C3e88A13",
|
||||
"CustomERC20GatewayAddr": "0x31C994F2017E71b82fd4D8118F140c81215bbb37",
|
||||
"ERC721GatewayAddr": "0xEF27A5E63aa3f1B8312f744b9b4DcEB910Ba77AC",
|
||||
"ERC1155GatewayAddr": "0xa5Df8530766A85936EE3E139dECE3bF081c83146",
|
||||
"DAIGatewayAddr": "0x8b0B9c4e9f41b9bbDEfFee24F9f11C328093d248",
|
||||
"ScrollChainAddr": "0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0",
|
||||
"GatewayRouterAddr": "0x13FBE0D0e5552b8c9c4AE9e2435F38f37355998a",
|
||||
"MessageQueueAddr": "0xF0B2293F5D834eAe920c6974D50957A1732de763"
|
||||
},
|
||||
"L2": {
|
||||
"confirmation": 0,
|
||||
"endpoint": "https://rpc.scroll.io",
|
||||
"confirmation": 1,
|
||||
"endpoint": "L2-URL",
|
||||
"blockTime": 3,
|
||||
"fetchLimit": 100,
|
||||
"MessengerAddr": "0x781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC",
|
||||
"ETHGatewayAddr": "0x6EA73e05AdC79974B931123675ea8F78FfdacDF0",
|
||||
"WETHGatewayAddr": "0x7003E7B7186f0E6601203b99F7B8DECBfA391cf9",
|
||||
"StandardERC20GatewayAddr": "0xE2b4795039517653c5Ae8C2A9BFdd783b48f447A",
|
||||
"CustomERC20GatewayAddr": "0x64CCBE37c9A82D85A1F2E74649b7A42923067988",
|
||||
"ERC721GatewayAddr": "0x7bC08E1c04fb41d75F1410363F0c5746Eae80582",
|
||||
"ERC1155GatewayAddr": "0x62597Cc19703aF10B58feF87B0d5D29eFE263bcc",
|
||||
"USDCGatewayAddr": "0x33B60d5Dd260d453cAC3782b0bDC01ce84672142",
|
||||
"LIDOGatewayAddr": "0x8aE8f22226B9d789A36AC81474e633f8bE2856c9",
|
||||
"DAIGatewayAddr": "0xaC78dff3A87b5b534e366A93E785a0ce8fA6Cc62",
|
||||
"GatewayRouterAddr": "0x4C0926FF5252A435FD19e10ED15e5a249Ba19d79"
|
||||
"fetchLimit": 128,
|
||||
"MessengerAddr": "0xBa50f5340FB9F3Bd074bD638c9BE13eCB36E603d",
|
||||
"ETHGatewayAddr": "0x91e8ADDFe1358aCa5314c644312d38237fC1101C",
|
||||
"WETHGatewayAddr": "0x481B20A927206aF7A754dB8b904B052e2781ea27",
|
||||
"StandardERC20GatewayAddr": "0xaDcA915971A336EA2f5b567e662F5bd74AEf9582",
|
||||
"CustomERC20GatewayAddr": "0x058dec71E53079F9ED053F3a0bBca877F6f3eAcf",
|
||||
"ERC721GatewayAddr": "0x179B9415194B67DC3c0b8760E075cD4415785c97",
|
||||
"ERC1155GatewayAddr": "0xe17C9b9C66FAF07753cdB04316D09f52144612A5",
|
||||
"DAIGatewayAddr": "0xbF28c28490988026Dca2396148DE50136A54534e",
|
||||
"GatewayRouterAddr": "0x9aD3c5617eCAa556d6E166787A97081907171230",
|
||||
"MessageQueueAddr": "0x5300000000000000000000000000000000000000"
|
||||
},
|
||||
"db": {
|
||||
"dsn": "postgres://postgres:123456@localhost:5444/test?sslmode=disable",
|
||||
@@ -44,10 +41,7 @@
|
||||
},
|
||||
"redis": {
|
||||
"address": "localhost:6379",
|
||||
"username": "default",
|
||||
"password": "",
|
||||
"local": true,
|
||||
"minIdleConns": 10,
|
||||
"readTimeoutMs": 500
|
||||
"db": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
type LayerConfig struct {
|
||||
Confirmation uint64 `json:"confirmation"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
StartHeight uint64 `json:"startHeight"` // Can only be configured to contract deployment height, otherwise in the current implementation, the message proof could not be successfully updated.
|
||||
StartHeight uint64 `json:"startHeight"`
|
||||
BlockTime int64 `json:"blockTime"`
|
||||
FetchLimit uint64 `json:"fetchLimit"`
|
||||
MessengerAddr string `json:"MessengerAddr"`
|
||||
@@ -32,13 +32,9 @@ type LayerConfig struct {
|
||||
|
||||
// RedisConfig redis config
|
||||
type RedisConfig struct {
|
||||
Address string `json:"address"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
DB int `json:"db"`
|
||||
Local bool `json:"local"`
|
||||
MinIdleConns int `json:"minIdleConns"`
|
||||
ReadTimeoutMs int `json:"readTimeoutMs"`
|
||||
Address string `json:"address"`
|
||||
Password string `json:"password"`
|
||||
DB int `json:"db"`
|
||||
}
|
||||
|
||||
// Config is the configuration of the bridge history backend
|
||||
|
||||
@@ -35,7 +35,7 @@ func (c *HistoryController) GetL2UnclaimedWithdrawalsByAddress(ctx *gin.Context)
|
||||
return
|
||||
}
|
||||
|
||||
resultData := &types.ResultData{Results: pagedTxs, Total: total}
|
||||
resultData := &types.ResultData{Result: pagedTxs, Total: total}
|
||||
types.RenderSuccess(ctx, resultData)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func (c *HistoryController) GetL2WithdrawalsByAddress(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
resultData := &types.ResultData{Results: pagedTxs, Total: total}
|
||||
resultData := &types.ResultData{Result: pagedTxs, Total: total}
|
||||
types.RenderSuccess(ctx, resultData)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (c *HistoryController) GetTxsByAddress(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
resultData := &types.ResultData{Results: pagedTxs, Total: total}
|
||||
resultData := &types.ResultData{Result: pagedTxs, Total: total}
|
||||
types.RenderSuccess(ctx, resultData)
|
||||
}
|
||||
|
||||
@@ -89,6 +89,6 @@ func (c *HistoryController) PostQueryTxsByHashes(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
resultData := &types.ResultData{Results: results, Total: uint64(len(results))}
|
||||
resultData := &types.ResultData{Result: results, Total: uint64(len(results))}
|
||||
types.RenderSuccess(ctx, resultData)
|
||||
}
|
||||
|
||||
@@ -2,12 +2,8 @@ package fetcher
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
"github.com/scroll-tech/go-ethereum/log"
|
||||
"gorm.io/gorm"
|
||||
@@ -23,75 +19,41 @@ type L1MessageFetcher struct {
|
||||
cfg *config.LayerConfig
|
||||
client *ethclient.Client
|
||||
|
||||
l1SyncHeight uint64
|
||||
l1LastSyncBlockHash common.Hash
|
||||
syncInfo *SyncInfo
|
||||
l1ScanHeight uint64
|
||||
|
||||
eventUpdateLogic *logic.EventUpdateLogic
|
||||
l1FetcherLogic *logic.L1FetcherLogic
|
||||
|
||||
l1MessageFetcherRunningTotal prometheus.Counter
|
||||
l1MessageFetcherReorgTotal prometheus.Counter
|
||||
l1MessageFetcherSyncHeight prometheus.Gauge
|
||||
}
|
||||
|
||||
// NewL1MessageFetcher creates a new L1MessageFetcher instance.
|
||||
func NewL1MessageFetcher(ctx context.Context, cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client) *L1MessageFetcher {
|
||||
c := &L1MessageFetcher{
|
||||
func NewL1MessageFetcher(ctx context.Context, cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client, syncInfo *SyncInfo) (*L1MessageFetcher, error) {
|
||||
return &L1MessageFetcher{
|
||||
ctx: ctx,
|
||||
cfg: cfg,
|
||||
client: client,
|
||||
eventUpdateLogic: logic.NewEventUpdateLogic(db, true),
|
||||
syncInfo: syncInfo,
|
||||
eventUpdateLogic: logic.NewEventUpdateLogic(db),
|
||||
l1FetcherLogic: logic.NewL1FetcherLogic(cfg, db, client),
|
||||
}
|
||||
|
||||
reg := prometheus.DefaultRegisterer
|
||||
c.l1MessageFetcherRunningTotal = promauto.With(reg).NewCounter(prometheus.CounterOpts{
|
||||
Name: "L1_message_fetcher_running_total",
|
||||
Help: "Current count of running L1 message fetcher instances.",
|
||||
})
|
||||
c.l1MessageFetcherReorgTotal = promauto.With(reg).NewCounter(prometheus.CounterOpts{
|
||||
Name: "L1_message_fetcher_reorg_total",
|
||||
Help: "Total count of blockchain reorgs encountered by the L1 message fetcher.",
|
||||
})
|
||||
c.l1MessageFetcherSyncHeight = promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "L1_message_fetcher_sync_height",
|
||||
Help: "Latest blockchain height the L1 message fetcher has synced with.",
|
||||
})
|
||||
|
||||
return c
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start starts the L1 message fetching process.
|
||||
func (c *L1MessageFetcher) Start() {
|
||||
messageSyncedHeight, batchSyncedHeight, dbErr := c.eventUpdateLogic.GetL1SyncHeight(c.ctx)
|
||||
if dbErr != nil {
|
||||
log.Crit("L1MessageFetcher start failed", "err", dbErr)
|
||||
}
|
||||
|
||||
l1SyncHeight := messageSyncedHeight
|
||||
if batchSyncedHeight > l1SyncHeight {
|
||||
l1SyncHeight = batchSyncedHeight
|
||||
}
|
||||
if c.cfg.StartHeight > l1SyncHeight {
|
||||
l1SyncHeight = c.cfg.StartHeight - 1
|
||||
}
|
||||
|
||||
// Sync from an older block to prevent reorg during restart.
|
||||
if l1SyncHeight < logic.L1ReorgSafeDepth {
|
||||
l1SyncHeight = 0
|
||||
} else {
|
||||
l1SyncHeight -= logic.L1ReorgSafeDepth
|
||||
}
|
||||
|
||||
header, err := c.client.HeaderByNumber(c.ctx, new(big.Int).SetUint64(l1SyncHeight))
|
||||
messageSyncedHeight, batchSyncedHeight, err := c.eventUpdateLogic.GetL1SyncHeight(c.ctx)
|
||||
if err != nil {
|
||||
log.Crit("failed to get L1 header by number", "block number", l1SyncHeight, "err", err)
|
||||
return
|
||||
log.Crit("L1MessageFetcher start failed", "error", err)
|
||||
}
|
||||
|
||||
c.updateL1SyncHeight(l1SyncHeight, header.Hash())
|
||||
c.l1ScanHeight = messageSyncedHeight
|
||||
if batchSyncedHeight > c.l1ScanHeight {
|
||||
c.l1ScanHeight = batchSyncedHeight
|
||||
}
|
||||
if c.cfg.StartHeight > c.l1ScanHeight {
|
||||
c.l1ScanHeight = c.cfg.StartHeight - 1
|
||||
}
|
||||
|
||||
log.Info("Start L1 message fetcher", "message synced height", messageSyncedHeight, "batch synced height", batchSyncedHeight, "config start height", c.cfg.StartHeight, "sync start height", c.l1SyncHeight+1)
|
||||
log.Info("Start L1 message fetcher", "message synced height", messageSyncedHeight, "batch synced height", batchSyncedHeight, "config start height", c.cfg.StartHeight)
|
||||
|
||||
tick := time.NewTicker(time.Duration(c.cfg.BlockTime) * time.Second)
|
||||
go func() {
|
||||
@@ -108,15 +70,13 @@ func (c *L1MessageFetcher) Start() {
|
||||
}
|
||||
|
||||
func (c *L1MessageFetcher) fetchAndSaveEvents(confirmation uint64) {
|
||||
c.l1MessageFetcherRunningTotal.Inc()
|
||||
startHeight := c.l1SyncHeight + 1
|
||||
endHeight, rpcErr := utils.GetBlockNumber(c.ctx, c.client, confirmation)
|
||||
if rpcErr != nil {
|
||||
log.Error("failed to get L1 block number", "confirmation", confirmation, "err", rpcErr)
|
||||
startHeight := c.l1ScanHeight + 1
|
||||
endHeight, err := utils.GetBlockNumber(c.ctx, c.client, confirmation)
|
||||
if err != nil {
|
||||
log.Error("failed to get L1 safe block number", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("fetch and save missing L1 events", "start height", startHeight, "end height", endHeight, "confirmation", confirmation)
|
||||
log.Info("fetch and save missing L1 events", "start height", startHeight, "end height", endHeight)
|
||||
|
||||
for from := startHeight; from <= endHeight; from += c.cfg.FetchLimit {
|
||||
to := from + c.cfg.FetchLimit - 1
|
||||
@@ -124,30 +84,27 @@ func (c *L1MessageFetcher) fetchAndSaveEvents(confirmation uint64) {
|
||||
to = endHeight
|
||||
}
|
||||
|
||||
isReorg, resyncHeight, lastBlockHash, l1FetcherResult, fetcherErr := c.l1FetcherLogic.L1Fetcher(c.ctx, from, to, c.l1LastSyncBlockHash)
|
||||
fetcherResult, fetcherErr := c.l1FetcherLogic.L1Fetcher(c.ctx, from, to)
|
||||
if fetcherErr != nil {
|
||||
log.Error("failed to fetch L1 events", "from", from, "to", to, "err", fetcherErr)
|
||||
log.Error("failed to fetch L1 events", "from", from, "to", to, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if isReorg {
|
||||
c.l1MessageFetcherReorgTotal.Inc()
|
||||
log.Warn("L1 reorg happened, exit and re-enter fetchAndSaveEvents", "re-sync height", resyncHeight)
|
||||
c.updateL1SyncHeight(resyncHeight, lastBlockHash)
|
||||
if insertUpdateErr := c.eventUpdateLogic.L1InsertOrUpdate(c.ctx, fetcherResult); insertUpdateErr != nil {
|
||||
log.Error("failed to save L1 events", "from", from, "to", to, "err", err)
|
||||
return
|
||||
}
|
||||
c.l1ScanHeight = to
|
||||
|
||||
l2ScannedHeight := c.syncInfo.GetL2ScanHeight()
|
||||
if l2ScannedHeight == 0 {
|
||||
log.Error("L2 fetcher has not successfully synced at least one round yet")
|
||||
return
|
||||
}
|
||||
|
||||
if insertUpdateErr := c.eventUpdateLogic.L1InsertOrUpdate(c.ctx, l1FetcherResult); insertUpdateErr != nil {
|
||||
log.Error("failed to save L1 events", "from", from, "to", to, "err", insertUpdateErr)
|
||||
if updateErr := c.eventUpdateLogic.UpdateL1BatchIndexAndStatus(c.ctx, l2ScannedHeight); updateErr != nil {
|
||||
log.Error("failed to update L1 batch index and status", "from", from, "to", to, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.updateL1SyncHeight(to, lastBlockHash)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *L1MessageFetcher) updateL1SyncHeight(height uint64, blockHash common.Hash) {
|
||||
c.l1MessageFetcherSyncHeight.Set(float64(height))
|
||||
c.l1LastSyncBlockHash = blockHash
|
||||
c.l1SyncHeight = height
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ package fetcher
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"github.com/scroll-tech/go-ethereum/ethclient"
|
||||
"github.com/scroll-tech/go-ethereum/log"
|
||||
@@ -14,79 +13,45 @@ import (
|
||||
|
||||
"scroll-tech/bridge-history-api/internal/config"
|
||||
"scroll-tech/bridge-history-api/internal/logic"
|
||||
"scroll-tech/bridge-history-api/internal/orm"
|
||||
"scroll-tech/bridge-history-api/internal/utils"
|
||||
)
|
||||
|
||||
// L2MessageFetcher fetches cross message events from L2 and saves them to database.
|
||||
type L2MessageFetcher struct {
|
||||
ctx context.Context
|
||||
cfg *config.LayerConfig
|
||||
db *gorm.DB
|
||||
client *ethclient.Client
|
||||
l2SyncHeight uint64
|
||||
l2LastSyncBlockHash common.Hash
|
||||
ctx context.Context
|
||||
cfg *config.LayerConfig
|
||||
db *gorm.DB
|
||||
client *ethclient.Client
|
||||
syncInfo *SyncInfo
|
||||
|
||||
eventUpdateLogic *logic.EventUpdateLogic
|
||||
l2FetcherLogic *logic.L2FetcherLogic
|
||||
|
||||
l2MessageFetcherRunningTotal prometheus.Counter
|
||||
l2MessageFetcherReorgTotal prometheus.Counter
|
||||
l2MessageFetcherSyncHeight prometheus.Gauge
|
||||
}
|
||||
|
||||
// NewL2MessageFetcher creates a new L2MessageFetcher instance.
|
||||
func NewL2MessageFetcher(ctx context.Context, cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client) *L2MessageFetcher {
|
||||
c := &L2MessageFetcher{
|
||||
func NewL2MessageFetcher(ctx context.Context, cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client, syncInfo *SyncInfo) (*L2MessageFetcher, error) {
|
||||
return &L2MessageFetcher{
|
||||
ctx: ctx,
|
||||
cfg: cfg,
|
||||
db: db,
|
||||
syncInfo: syncInfo,
|
||||
client: client,
|
||||
eventUpdateLogic: logic.NewEventUpdateLogic(db, false),
|
||||
eventUpdateLogic: logic.NewEventUpdateLogic(db),
|
||||
l2FetcherLogic: logic.NewL2FetcherLogic(cfg, db, client),
|
||||
}
|
||||
|
||||
reg := prometheus.DefaultRegisterer
|
||||
c.l2MessageFetcherRunningTotal = promauto.With(reg).NewCounter(prometheus.CounterOpts{
|
||||
Name: "L2_message_fetcher_running_total",
|
||||
Help: "Current count of running L2 message fetcher instances.",
|
||||
})
|
||||
c.l2MessageFetcherReorgTotal = promauto.With(reg).NewCounter(prometheus.CounterOpts{
|
||||
Name: "L2_message_fetcher_reorg_total",
|
||||
Help: "Total count of blockchain reorgs encountered by the L2 message fetcher.",
|
||||
})
|
||||
c.l2MessageFetcherSyncHeight = promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "L2_message_fetcher_sync_height",
|
||||
Help: "Latest blockchain height the L2 message fetcher has synced with.",
|
||||
})
|
||||
|
||||
return c
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start starts the L2 message fetching process.
|
||||
func (c *L2MessageFetcher) Start() {
|
||||
l2SentMessageSyncedHeight, dbErr := c.eventUpdateLogic.GetL2MessageSyncedHeightInDB(c.ctx)
|
||||
if dbErr != nil {
|
||||
log.Crit("failed to get L2 cross message processed height", "err", dbErr)
|
||||
return
|
||||
}
|
||||
|
||||
l2SyncHeight := l2SentMessageSyncedHeight
|
||||
// Sync from an older block to prevent reorg during restart.
|
||||
if l2SyncHeight < logic.L2ReorgSafeDepth {
|
||||
l2SyncHeight = 0
|
||||
} else {
|
||||
l2SyncHeight -= logic.L2ReorgSafeDepth
|
||||
}
|
||||
|
||||
header, err := c.client.HeaderByNumber(c.ctx, new(big.Int).SetUint64(l2SyncHeight))
|
||||
l2SentMessageSyncedHeight, err := c.eventUpdateLogic.GetL2MessageSyncedHeightInDB(c.ctx)
|
||||
if err != nil {
|
||||
log.Crit("failed to get L2 header by number", "block number", l2SyncHeight, "err", err)
|
||||
log.Error("failed to get L2 cross message processed height", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.updateL2SyncHeight(l2SyncHeight, header.Hash())
|
||||
|
||||
log.Info("Start L2 message fetcher", "message synced height", l2SentMessageSyncedHeight, "sync start height", l2SyncHeight+1)
|
||||
c.syncInfo.SetL2ScanHeight(l2SentMessageSyncedHeight)
|
||||
log.Info("Start L2 message fetcher", "message synced height", l2SentMessageSyncedHeight)
|
||||
|
||||
tick := time.NewTicker(time.Duration(c.cfg.BlockTime) * time.Second)
|
||||
go func() {
|
||||
@@ -103,14 +68,13 @@ func (c *L2MessageFetcher) Start() {
|
||||
}
|
||||
|
||||
func (c *L2MessageFetcher) fetchAndSaveEvents(confirmation uint64) {
|
||||
startHeight := c.l2SyncHeight + 1
|
||||
endHeight, rpcErr := utils.GetBlockNumber(c.ctx, c.client, confirmation)
|
||||
if rpcErr != nil {
|
||||
log.Error("failed to get L2 block number", "confirmation", confirmation, "err", rpcErr)
|
||||
startHeight := c.syncInfo.GetL2ScanHeight() + 1
|
||||
endHeight, err := utils.GetBlockNumber(c.ctx, c.client, confirmation)
|
||||
if err != nil {
|
||||
log.Error("failed to get L1 safe block number", "err", err)
|
||||
return
|
||||
}
|
||||
log.Info("fetch and save missing L2 events", "start height", startHeight, "end height", endHeight, "confirmation", confirmation)
|
||||
c.l2MessageFetcherRunningTotal.Inc()
|
||||
log.Info("fetch and save missing L2 events", "start height", startHeight, "end height", endHeight)
|
||||
|
||||
for from := startHeight; from <= endHeight; from += c.cfg.FetchLimit {
|
||||
to := from + c.cfg.FetchLimit - 1
|
||||
@@ -118,35 +82,67 @@ func (c *L2MessageFetcher) fetchAndSaveEvents(confirmation uint64) {
|
||||
to = endHeight
|
||||
}
|
||||
|
||||
isReorg, resyncHeight, lastBlockHash, l2FetcherResult, fetcherErr := c.l2FetcherLogic.L2Fetcher(c.ctx, from, to, c.l2LastSyncBlockHash)
|
||||
if fetcherErr != nil {
|
||||
log.Error("failed to fetch L2 events", "from", from, "to", to, "err", fetcherErr)
|
||||
l2FilterResult, err := c.l2FetcherLogic.L2Fetcher(c.ctx, from, to)
|
||||
if err != nil {
|
||||
log.Error("failed to fetch L2 events", "from", from, "to", to, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if isReorg {
|
||||
c.l2MessageFetcherReorgTotal.Inc()
|
||||
log.Warn("L2 reorg happened, exit and re-enter fetchAndSaveEvents", "re-sync height", resyncHeight)
|
||||
c.updateL2SyncHeight(resyncHeight, lastBlockHash)
|
||||
if updateWithdrawErr := c.updateL2WithdrawMessageProofs(c.ctx, l2FilterResult.WithdrawMessages, to); updateWithdrawErr != nil {
|
||||
log.Error("failed to update L2 withdraw message", "from", from, "to", to, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if insertUpdateErr := c.eventUpdateLogic.L2InsertOrUpdate(c.ctx, l2FetcherResult); insertUpdateErr != nil {
|
||||
log.Error("failed to save L2 events", "from", from, "to", to, "err", insertUpdateErr)
|
||||
if insertUpdateErr := c.eventUpdateLogic.L2InsertOrUpdate(c.ctx, l2FilterResult); insertUpdateErr != nil {
|
||||
log.Error("failed to save L2 events", "from", from, "to", to, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if updateErr := c.eventUpdateLogic.UpdateL1BatchIndexAndStatus(c.ctx, c.l2SyncHeight); updateErr != nil {
|
||||
log.Error("failed to update L1 batch index and status", "from", from, "to", to, "err", updateErr)
|
||||
return
|
||||
}
|
||||
|
||||
c.updateL2SyncHeight(to, lastBlockHash)
|
||||
c.syncInfo.SetL2ScanHeight(to)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *L2MessageFetcher) updateL2SyncHeight(height uint64, blockHash common.Hash) {
|
||||
c.l2MessageFetcherSyncHeight.Set(float64(height))
|
||||
c.l2LastSyncBlockHash = blockHash
|
||||
c.l2SyncHeight = height
|
||||
func (c *L2MessageFetcher) updateL2WithdrawMessageProofs(ctx context.Context, l2WithdrawMessages []*orm.CrossMessage, endBlock uint64) error {
|
||||
withdrawTrie := utils.NewWithdrawTrie()
|
||||
message, err := c.eventUpdateLogic.GetL2LatestWithdrawal(ctx)
|
||||
if err != nil {
|
||||
log.Error("failed to get latest L2 sent message event", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if message != nil {
|
||||
withdrawTrie.Initialize(message.MessageNonce, common.HexToHash(message.MessageHash), message.MerkleProof)
|
||||
}
|
||||
|
||||
messageHashes := make([]common.Hash, len(l2WithdrawMessages))
|
||||
for i, message := range l2WithdrawMessages {
|
||||
messageHashes[i] = common.HexToHash(message.MessageHash)
|
||||
}
|
||||
|
||||
for i, messageHash := range messageHashes {
|
||||
proof := withdrawTrie.AppendMessages([]common.Hash{messageHash})
|
||||
if err != nil {
|
||||
log.Error("error generating proof", "messageHash", messageHash, "error", err)
|
||||
return fmt.Errorf("error generating proof for messageHash %s: %v", messageHash, err)
|
||||
}
|
||||
|
||||
if len(proof) != 1 {
|
||||
log.Error("invalid proof len", "got", len(proof), "expected", 1)
|
||||
return fmt.Errorf("invalid proof len, got: %v, expected: 1", len(proof))
|
||||
}
|
||||
l2WithdrawMessages[i].MerkleProof = proof[0]
|
||||
}
|
||||
|
||||
// Verify if local info is correct.
|
||||
withdrawRoot, err := c.client.StorageAt(ctx, common.HexToAddress(c.cfg.MessageQueueAddr), common.Hash{}, new(big.Int).SetUint64(endBlock))
|
||||
if err != nil {
|
||||
log.Error("failed to get withdraw root", "number", endBlock, "error", err)
|
||||
return fmt.Errorf("failed to get withdraw root: %v, number: %v", err, endBlock)
|
||||
}
|
||||
|
||||
if common.BytesToHash(withdrawRoot) != withdrawTrie.MessageRoot() {
|
||||
log.Error("withdraw root mismatch", "expected", common.BytesToHash(withdrawRoot).String(), "got", withdrawTrie.MessageRoot().String())
|
||||
return fmt.Errorf("withdraw root mismatch. expected: %v, got: %v", common.BytesToHash(withdrawRoot), withdrawTrie.MessageRoot())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
18
bridge-history-api/internal/controller/fetcher/sync.go
Normal file
18
bridge-history-api/internal/controller/fetcher/sync.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package fetcher
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// SyncInfo is a struct that stores synchronization information shared between L1 fetcher and L2 fetcher.
|
||||
type SyncInfo struct {
|
||||
l2ScanHeight uint64
|
||||
}
|
||||
|
||||
// SetL2ScanHeight is a method that sets the value of l2ScanHeight in SyncInfo.
|
||||
func (s *SyncInfo) SetL2ScanHeight(height uint64) {
|
||||
atomic.StoreUint64(&s.l2ScanHeight, height)
|
||||
}
|
||||
|
||||
// GetL2ScanHeight is a method that retrieves the value of l2ScanHeight in SyncInfo.
|
||||
func (s *SyncInfo) GetL2ScanHeight() uint64 {
|
||||
return atomic.LoadUint64(&s.l2ScanHeight)
|
||||
}
|
||||
@@ -2,16 +2,11 @@ package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"github.com/scroll-tech/go-ethereum/log"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"scroll-tech/bridge-history-api/internal/orm"
|
||||
"scroll-tech/bridge-history-api/internal/utils"
|
||||
)
|
||||
|
||||
// EventUpdateLogic the logic of insert/update the database
|
||||
@@ -19,35 +14,18 @@ type EventUpdateLogic struct {
|
||||
db *gorm.DB
|
||||
crossMessageOrm *orm.CrossMessage
|
||||
batchEventOrm *orm.BatchEvent
|
||||
|
||||
eventUpdateLogicL1FinalizeBatchEventL2BlockUpdateHeight prometheus.Gauge
|
||||
eventUpdateLogicL2MessageNonceUpdateHeight prometheus.Gauge
|
||||
}
|
||||
|
||||
// NewEventUpdateLogic creates a EventUpdateLogic instance
|
||||
func NewEventUpdateLogic(db *gorm.DB, isL1 bool) *EventUpdateLogic {
|
||||
b := &EventUpdateLogic{
|
||||
// NewEventUpdateLogic create a EventUpdateLogic instance
|
||||
func NewEventUpdateLogic(db *gorm.DB) *EventUpdateLogic {
|
||||
return &EventUpdateLogic{
|
||||
db: db,
|
||||
crossMessageOrm: orm.NewCrossMessage(db),
|
||||
batchEventOrm: orm.NewBatchEvent(db),
|
||||
}
|
||||
|
||||
if !isL1 {
|
||||
reg := prometheus.DefaultRegisterer
|
||||
b.eventUpdateLogicL1FinalizeBatchEventL2BlockUpdateHeight = promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "event_update_logic_L1_finalize_batch_event_L2_block_update_height",
|
||||
Help: "L2 block height of the latest L1 batch event that has been finalized and updated in the message_table.",
|
||||
})
|
||||
b.eventUpdateLogicL2MessageNonceUpdateHeight = promauto.With(reg).NewGauge(prometheus.GaugeOpts{
|
||||
Name: "event_update_logic_L2_message_nonce_update_height",
|
||||
Help: "L2 message nonce height in the latest L1 batch event that has been finalized and updated in the message_table.",
|
||||
})
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// GetL1SyncHeight gets the l1 sync height from db
|
||||
// GetL1SyncHeight get the l1 sync height from db
|
||||
func (b *EventUpdateLogic) GetL1SyncHeight(ctx context.Context) (uint64, uint64, error) {
|
||||
messageSyncedHeight, err := b.crossMessageOrm.GetMessageSyncedHeightInDB(ctx, orm.MessageTypeL1SentMessage)
|
||||
if err != nil {
|
||||
@@ -64,7 +42,7 @@ func (b *EventUpdateLogic) GetL1SyncHeight(ctx context.Context) (uint64, uint64,
|
||||
return messageSyncedHeight, batchSyncedHeight, nil
|
||||
}
|
||||
|
||||
// GetL2MessageSyncedHeightInDB gets L2 messages synced height
|
||||
// GetL2MessageSyncedHeightInDB get L2 messages synced height
|
||||
func (b *EventUpdateLogic) GetL2MessageSyncedHeightInDB(ctx context.Context) (uint64, error) {
|
||||
l2SentMessageSyncedHeight, err := b.crossMessageOrm.GetMessageSyncedHeightInDB(ctx, orm.MessageTypeL2SentMessage)
|
||||
if err != nil {
|
||||
@@ -74,7 +52,17 @@ func (b *EventUpdateLogic) GetL2MessageSyncedHeightInDB(ctx context.Context) (ui
|
||||
return l2SentMessageSyncedHeight, nil
|
||||
}
|
||||
|
||||
// L1InsertOrUpdate inserts or updates l1 messages
|
||||
// GetL2LatestWithdrawal get L2 latest withdrawal message
|
||||
func (b *EventUpdateLogic) GetL2LatestWithdrawal(ctx context.Context) (*orm.CrossMessage, error) {
|
||||
message, err := b.crossMessageOrm.GetLatestL2Withdrawal(ctx)
|
||||
if err != nil {
|
||||
log.Error("failed to get latest L2 sent message event", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
return message, nil
|
||||
}
|
||||
|
||||
// L1InsertOrUpdate insert or update l1 messages
|
||||
func (b *EventUpdateLogic) L1InsertOrUpdate(ctx context.Context, l1FetcherResult *L1FilterResult) error {
|
||||
err := b.db.Transaction(func(tx *gorm.DB) error {
|
||||
if txErr := b.crossMessageOrm.InsertOrUpdateL1Messages(ctx, l1FetcherResult.DepositMessages, tx); txErr != nil {
|
||||
@@ -97,7 +85,7 @@ func (b *EventUpdateLogic) L1InsertOrUpdate(ctx context.Context, l1FetcherResult
|
||||
return txErr
|
||||
}
|
||||
|
||||
if txErr := b.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l1FetcherResult.RevertedTxs, tx); txErr != nil {
|
||||
if txErr := b.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l1FetcherResult.FailedGatewayRouterTxs, tx); txErr != nil {
|
||||
log.Error("failed to insert L1 failed gateway router transactions", "err", txErr)
|
||||
return txErr
|
||||
}
|
||||
@@ -112,79 +100,30 @@ func (b *EventUpdateLogic) L1InsertOrUpdate(ctx context.Context, l1FetcherResult
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *EventUpdateLogic) updateL2WithdrawMessageInfos(ctx context.Context, batchIndex, startBlock, endBlock uint64) error {
|
||||
l2WithdrawMessages, err := b.crossMessageOrm.GetL2WithdrawalsByBlockRange(ctx, startBlock, endBlock)
|
||||
if err != nil {
|
||||
log.Error("failed to get L2 withdrawals by batch index", "batch index", batchIndex, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(l2WithdrawMessages) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
withdrawTrie := utils.NewWithdrawTrie()
|
||||
lastMessage, err := b.crossMessageOrm.GetL2LatestFinalizedWithdrawal(ctx)
|
||||
if err != nil {
|
||||
log.Error("failed to get latest L2 finalized sent message event", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if lastMessage != nil {
|
||||
withdrawTrie.Initialize(lastMessage.MessageNonce, common.HexToHash(lastMessage.MessageHash), lastMessage.MerkleProof)
|
||||
}
|
||||
|
||||
if withdrawTrie.NextMessageNonce != l2WithdrawMessages[0].MessageNonce {
|
||||
log.Error("nonce mismatch", "expected next message nonce", withdrawTrie.NextMessageNonce, "actuall next message nonce", l2WithdrawMessages[0].MessageNonce)
|
||||
return fmt.Errorf("nonce mismatch")
|
||||
}
|
||||
|
||||
messageHashes := make([]common.Hash, len(l2WithdrawMessages))
|
||||
for i, message := range l2WithdrawMessages {
|
||||
messageHashes[i] = common.HexToHash(message.MessageHash)
|
||||
}
|
||||
|
||||
proofs := withdrawTrie.AppendMessages(messageHashes)
|
||||
|
||||
for i, message := range l2WithdrawMessages {
|
||||
message.MerkleProof = proofs[i]
|
||||
message.RollupStatus = int(orm.RollupStatusTypeFinalized)
|
||||
message.BatchIndex = batchIndex
|
||||
}
|
||||
|
||||
if dbErr := b.crossMessageOrm.UpdateBatchIndexRollupStatusMerkleProofOfL2Messages(ctx, l2WithdrawMessages); dbErr != nil {
|
||||
log.Error("failed to update batch index and rollup status and merkle proof of L2 messages", "err", dbErr)
|
||||
return dbErr
|
||||
}
|
||||
|
||||
b.eventUpdateLogicL2MessageNonceUpdateHeight.Set(float64(withdrawTrie.NextMessageNonce - 1))
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateL1BatchIndexAndStatus updates L1 finalized batch index and status
|
||||
// UpdateL1BatchIndexAndStatus update l1 batch index and status
|
||||
func (b *EventUpdateLogic) UpdateL1BatchIndexAndStatus(ctx context.Context, height uint64) error {
|
||||
finalizedBatches, err := b.batchEventOrm.GetFinalizedBatchesLEBlockHeight(ctx, height)
|
||||
batches, err := b.batchEventOrm.GetBatchesLEBlockHeight(ctx, height)
|
||||
if err != nil {
|
||||
log.Error("failed to get batches >= block height", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, finalizedBatch := range finalizedBatches {
|
||||
log.Info("update finalized batch info of L2 withdrawals", "index", finalizedBatch.BatchIndex, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber)
|
||||
if updateErr := b.updateL2WithdrawMessageInfos(ctx, finalizedBatch.BatchIndex, finalizedBatch.StartBlockNumber, finalizedBatch.EndBlockNumber); updateErr != nil {
|
||||
log.Error("failed to update L2 withdraw message infos", "index", finalizedBatch.BatchIndex, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber, "error", updateErr)
|
||||
return updateErr
|
||||
}
|
||||
if dbErr := b.batchEventOrm.UpdateBatchEventStatus(ctx, finalizedBatch.BatchIndex); dbErr != nil {
|
||||
log.Error("failed to update batch event status as updated", "index", finalizedBatch.BatchIndex, "start", finalizedBatch.StartBlockNumber, "end", finalizedBatch.EndBlockNumber, "error", dbErr)
|
||||
for _, batch := range batches {
|
||||
log.Info("update batch info of L2 withdrawals", "index", batch.BatchIndex, "start", batch.StartBlockNumber, "end", batch.EndBlockNumber)
|
||||
if dbErr := b.crossMessageOrm.UpdateBatchStatusOfL2Withdrawals(ctx, batch.StartBlockNumber, batch.EndBlockNumber, batch.BatchIndex); dbErr != nil {
|
||||
log.Error("failed to update batch status of L2 sent messages", "start", batch.StartBlockNumber, "end", batch.EndBlockNumber, "index", batch.BatchIndex, "error", dbErr)
|
||||
return dbErr
|
||||
}
|
||||
if dbErr := b.batchEventOrm.UpdateBatchEventStatus(ctx, batch.BatchIndex); dbErr != nil {
|
||||
log.Error("failed to update batch event status as updated", "start", batch.StartBlockNumber, "end", batch.EndBlockNumber, "index", batch.BatchIndex, "error", dbErr)
|
||||
return dbErr
|
||||
}
|
||||
b.eventUpdateLogicL1FinalizeBatchEventL2BlockUpdateHeight.Set(float64(finalizedBatch.EndBlockNumber))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// L2InsertOrUpdate inserts or updates L2 messages
|
||||
// L2InsertOrUpdate insert or update L2 messages
|
||||
func (b *EventUpdateLogic) L2InsertOrUpdate(ctx context.Context, l2FetcherResult *L2FilterResult) error {
|
||||
err := b.db.Transaction(func(tx *gorm.DB) error {
|
||||
if txErr := b.crossMessageOrm.InsertOrUpdateL2Messages(ctx, l2FetcherResult.WithdrawMessages, tx); txErr != nil {
|
||||
@@ -195,7 +134,11 @@ func (b *EventUpdateLogic) L2InsertOrUpdate(ctx context.Context, l2FetcherResult
|
||||
log.Error("failed to update L2 relayed messages of L1 deposits", "err", txErr)
|
||||
return txErr
|
||||
}
|
||||
if txErr := b.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l2FetcherResult.OtherRevertedTxs, tx); txErr != nil {
|
||||
if txErr := b.crossMessageOrm.InsertOrUpdateL2RevertedRelayedMessagesOfL1Deposits(ctx, l2FetcherResult.RevertedRelayedMessages, tx); txErr != nil {
|
||||
log.Error("failed to update L2 relayed messages of L1 deposits", "err", txErr)
|
||||
return txErr
|
||||
}
|
||||
if txErr := b.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l2FetcherResult.FailedGatewayRouterTxs, tx); txErr != nil {
|
||||
log.Error("failed to insert L2 failed gateway router transactions", "err", txErr)
|
||||
return txErr
|
||||
}
|
||||
|
||||
@@ -16,20 +16,13 @@ import (
|
||||
|
||||
"scroll-tech/bridge-history-api/internal/orm"
|
||||
"scroll-tech/bridge-history-api/internal/types"
|
||||
"scroll-tech/bridge-history-api/internal/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
// cacheKeyPrefixBridgeHistory serves as a specific namespace for all Redis cache keys
|
||||
// associated with the 'bridge-history' user. This prefix is used to enforce access controls
|
||||
// in Redis, allowing permissions to be set such that only users with the appropriate
|
||||
// access rights can read or write to keys starting with "bridge-history".
|
||||
cacheKeyPrefixBridgeHistory = "bridge-history-"
|
||||
|
||||
cacheKeyPrefixL2ClaimableWithdrawalsByAddr = cacheKeyPrefixBridgeHistory + "l2ClaimableWithdrawalsByAddr:"
|
||||
cacheKeyPrefixL2WithdrawalsByAddr = cacheKeyPrefixBridgeHistory + "l2WithdrawalsByAddr:"
|
||||
cacheKeyPrefixTxsByAddr = cacheKeyPrefixBridgeHistory + "txsByAddr:"
|
||||
cacheKeyPrefixQueryTxsByHashes = cacheKeyPrefixBridgeHistory + "queryTxsByHashes:"
|
||||
cacheKeyPrefixL2ClaimableWithdrawalsByAddr = "l2ClaimableWithdrawalsByAddr:"
|
||||
cacheKeyPrefixL2WithdrawalsByAddr = "l2WithdrawalsByAddr:"
|
||||
cacheKeyPrefixTxsByAddr = "txsByAddr:"
|
||||
cacheKeyPrefixQueryTxsByHashes = "queryTxsByHashes:"
|
||||
cacheKeyExpiredTime = 1 * time.Minute
|
||||
)
|
||||
|
||||
@@ -262,44 +255,38 @@ func (h *HistoryLogic) GetTxsByHashes(ctx context.Context, txHashes []string) ([
|
||||
|
||||
func getTxHistoryInfo(message *orm.CrossMessage) *types.TxHistoryInfo {
|
||||
txHistory := &types.TxHistoryInfo{
|
||||
MessageHash: message.MessageHash,
|
||||
TokenType: orm.TokenType(message.TokenType),
|
||||
TokenIDs: utils.ConvertStringToStringArray(message.TokenIDs),
|
||||
TokenAmounts: utils.ConvertStringToStringArray(message.TokenAmounts),
|
||||
L1TokenAddress: message.L1TokenAddress,
|
||||
L2TokenAddress: message.L2TokenAddress,
|
||||
MessageType: orm.MessageType(message.MessageType),
|
||||
TxStatus: orm.TxStatusType(message.TxStatus),
|
||||
MsgHash: message.MessageHash,
|
||||
Amount: message.TokenAmounts,
|
||||
L1Token: message.L1TokenAddress,
|
||||
L2Token: message.L2TokenAddress,
|
||||
IsL1: orm.MessageType(message.MessageType) == orm.MessageTypeL1SentMessage,
|
||||
TxStatus: message.TxStatus,
|
||||
BlockTimestamp: message.BlockTimestamp,
|
||||
}
|
||||
if txHistory.MessageType == orm.MessageTypeL1SentMessage {
|
||||
if txHistory.IsL1 {
|
||||
txHistory.Hash = message.L1TxHash
|
||||
txHistory.ReplayTxHash = message.L1ReplayTxHash
|
||||
txHistory.RefundTxHash = message.L1RefundTxHash
|
||||
txHistory.BlockNumber = message.L1BlockNumber
|
||||
txHistory.CounterpartChainTx = &types.CounterpartChainTx{
|
||||
txHistory.FinalizeTx = &types.Finalized{
|
||||
Hash: message.L2TxHash,
|
||||
BlockNumber: message.L2BlockNumber,
|
||||
}
|
||||
} else {
|
||||
txHistory.Hash = message.L2TxHash
|
||||
txHistory.BlockNumber = message.L2BlockNumber
|
||||
txHistory.CounterpartChainTx = &types.CounterpartChainTx{
|
||||
txHistory.FinalizeTx = &types.Finalized{
|
||||
Hash: message.L1TxHash,
|
||||
BlockNumber: message.L1BlockNumber,
|
||||
}
|
||||
if orm.RollupStatusType(message.RollupStatus) == orm.RollupStatusTypeFinalized {
|
||||
txHistory.ClaimInfo = &types.ClaimInfo{
|
||||
From: message.MessageFrom,
|
||||
To: message.MessageTo,
|
||||
Value: message.MessageValue,
|
||||
Nonce: strconv.FormatUint(message.MessageNonce, 10),
|
||||
Message: message.MessageData,
|
||||
Proof: types.L2MessageProof{
|
||||
BatchIndex: strconv.FormatUint(message.BatchIndex, 10),
|
||||
MerkleProof: "0x" + common.Bytes2Hex(message.MerkleProof),
|
||||
},
|
||||
Claimable: true,
|
||||
txHistory.ClaimInfo = &types.UserClaimInfo{
|
||||
From: message.MessageFrom,
|
||||
To: message.MessageTo,
|
||||
Value: message.MessageValue,
|
||||
Nonce: strconv.FormatUint(message.MessageNonce, 10),
|
||||
Message: message.MessageData,
|
||||
Proof: "0x" + common.Bytes2Hex(message.MerkleProof),
|
||||
BatchIndex: strconv.FormatUint(message.BatchIndex, 10),
|
||||
Claimable: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ package logic
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/log"
|
||||
|
||||
@@ -18,7 +16,7 @@ import (
|
||||
type L1EventParser struct {
|
||||
}
|
||||
|
||||
// NewL1EventParser creates l1 event parser
|
||||
// NewL1EventParser create l1 event parser
|
||||
func NewL1EventParser() *L1EventParser {
|
||||
return &L1EventParser{}
|
||||
}
|
||||
@@ -217,12 +215,7 @@ func (e *L1EventParser) ParseL1BatchEventLogs(ctx context.Context, logs []types.
|
||||
}
|
||||
|
||||
// ParseL1MessageQueueEventLogs parses L1 watched message queue events.
|
||||
func (e *L1EventParser) ParseL1MessageQueueEventLogs(logs []types.Log, l1DepositMessages []*orm.CrossMessage) ([]*orm.MessageQueueEvent, error) {
|
||||
messageHashes := make(map[common.Hash]struct{})
|
||||
for _, msg := range l1DepositMessages {
|
||||
messageHashes[common.HexToHash(msg.MessageHash)] = struct{}{}
|
||||
}
|
||||
|
||||
func (e *L1EventParser) ParseL1MessageQueueEventLogs(logs []types.Log) ([]*orm.MessageQueueEvent, error) {
|
||||
var l1MessageQueueEvents []*orm.MessageQueueEvent
|
||||
for _, vlog := range logs {
|
||||
switch vlog.Topics[0] {
|
||||
@@ -232,16 +225,13 @@ func (e *L1EventParser) ParseL1MessageQueueEventLogs(logs []types.Log, l1Deposit
|
||||
log.Warn("Failed to unpack QueueTransaction event", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
messageHash := common.BytesToHash(crypto.Keccak256(event.Data))
|
||||
// If the message hash is not found in the map, it's not a replayMessage or enforced tx (omitted); add it to the events.
|
||||
if _, exists := messageHashes[messageHash]; !exists {
|
||||
l1MessageQueueEvents = append(l1MessageQueueEvents, &orm.MessageQueueEvent{
|
||||
EventType: orm.MessageQueueEventTypeQueueTransaction,
|
||||
QueueIndex: event.QueueIndex,
|
||||
MessageHash: messageHash,
|
||||
TxHash: vlog.TxHash,
|
||||
})
|
||||
}
|
||||
// 1. Update queue index of both sent message and replay message.
|
||||
// 2. Update tx hash of replay message.
|
||||
l1MessageQueueEvents = append(l1MessageQueueEvents, &orm.MessageQueueEvent{
|
||||
EventType: orm.MessageQueueEventTypeQueueTransaction,
|
||||
QueueIndex: event.QueueIndex,
|
||||
TxHash: vlog.TxHash,
|
||||
})
|
||||
case backendabi.L1DequeueTransactionEventSig:
|
||||
event := backendabi.L1DequeueTransactionEvent{}
|
||||
if err := utils.UnpackLog(backendabi.IL1MessageQueueABI, &event, "DequeueTransaction", vlog); err != nil {
|
||||
@@ -264,7 +254,6 @@ func (e *L1EventParser) ParseL1MessageQueueEventLogs(logs []types.Log, l1Deposit
|
||||
l1MessageQueueEvents = append(l1MessageQueueEvents, &orm.MessageQueueEvent{
|
||||
EventType: orm.MessageQueueEventTypeDropTransaction,
|
||||
QueueIndex: event.Index.Uint64(),
|
||||
TxHash: vlog.TxHash,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/scroll-tech/go-ethereum"
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"github.com/scroll-tech/go-ethereum/core/types"
|
||||
@@ -19,20 +17,16 @@ import (
|
||||
"scroll-tech/bridge-history-api/internal/utils"
|
||||
)
|
||||
|
||||
// L1ReorgSafeDepth represents the number of block confirmations considered safe against L1 chain reorganizations.
|
||||
// Reorganizations at this depth under normal cases are extremely unlikely.
|
||||
const L1ReorgSafeDepth = 64
|
||||
|
||||
// L1FilterResult L1 fetcher result
|
||||
// L1FilterResult l1 fetcher result
|
||||
type L1FilterResult struct {
|
||||
DepositMessages []*orm.CrossMessage
|
||||
RelayedMessages []*orm.CrossMessage
|
||||
BatchEvents []*orm.BatchEvent
|
||||
MessageQueueEvents []*orm.MessageQueueEvent
|
||||
RevertedTxs []*orm.CrossMessage
|
||||
FailedGatewayRouterTxs []*orm.CrossMessage
|
||||
DepositMessages []*orm.CrossMessage
|
||||
RelayedMessages []*orm.CrossMessage
|
||||
BatchEvents []*orm.BatchEvent
|
||||
MessageQueueEvents []*orm.MessageQueueEvent
|
||||
}
|
||||
|
||||
// L1FetcherLogic the L1 fetcher logic
|
||||
// L1FetcherLogic the l1 fetcher's logic
|
||||
type L1FetcherLogic struct {
|
||||
cfg *config.LayerConfig
|
||||
client *ethclient.Client
|
||||
@@ -41,11 +35,9 @@ type L1FetcherLogic struct {
|
||||
db *gorm.DB
|
||||
crossMessageOrm *orm.CrossMessage
|
||||
batchEventOrm *orm.BatchEvent
|
||||
|
||||
l1FetcherLogicFetchedTotal *prometheus.CounterVec
|
||||
}
|
||||
|
||||
// NewL1FetcherLogic creates L1 fetcher logic
|
||||
// NewL1FetcherLogic create l1 fetcher logic
|
||||
func NewL1FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client) *L1FetcherLogic {
|
||||
addressList := []common.Address{
|
||||
common.HexToAddress(cfg.ETHGatewayAddr),
|
||||
@@ -66,17 +58,15 @@ func NewL1FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.C
|
||||
}
|
||||
|
||||
// Optional erc20 gateways.
|
||||
if common.HexToAddress(cfg.USDCGatewayAddr) != (common.Address{}) {
|
||||
if cfg.USDCGatewayAddr != "" {
|
||||
addressList = append(addressList, common.HexToAddress(cfg.USDCGatewayAddr))
|
||||
}
|
||||
|
||||
if common.HexToAddress(cfg.LIDOGatewayAddr) != (common.Address{}) {
|
||||
if cfg.LIDOGatewayAddr != "" {
|
||||
addressList = append(addressList, common.HexToAddress(cfg.LIDOGatewayAddr))
|
||||
}
|
||||
|
||||
log.Info("L1 Fetcher configured with the following address list", "addresses", addressList)
|
||||
|
||||
f := &L1FetcherLogic{
|
||||
return &L1FetcherLogic{
|
||||
db: db,
|
||||
crossMessageOrm: orm.NewCrossMessage(db),
|
||||
batchEventOrm: orm.NewBatchEvent(db),
|
||||
@@ -85,47 +75,17 @@ func NewL1FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.C
|
||||
addressList: addressList,
|
||||
parser: NewL1EventParser(),
|
||||
}
|
||||
|
||||
reg := prometheus.DefaultRegisterer
|
||||
f.l1FetcherLogicFetchedTotal = promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "L1_fetcher_logic_fetched_total",
|
||||
Help: "The total number of events or failed txs fetched in L1 fetcher logic.",
|
||||
}, []string{"type"})
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *L1FetcherLogic) getBlocksAndDetectReorg(ctx context.Context, from, to uint64, lastBlockHash common.Hash) (bool, uint64, common.Hash, []*types.Block, error) {
|
||||
func (f *L1FetcherLogic) gatewayRouterFailedTxs(ctx context.Context, from, to uint64) (map[uint64]uint64, []*orm.CrossMessage, error) {
|
||||
blocks, err := utils.GetL1BlocksInRange(ctx, f.client, from, to)
|
||||
if err != nil {
|
||||
log.Error("failed to get L1 blocks in range", "from", from, "to", to, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, block := range blocks {
|
||||
if block.ParentHash() != lastBlockHash {
|
||||
log.Warn("L1 reorg detected", "reorg height", block.NumberU64()-1, "expected hash", block.ParentHash().String(), "local hash", lastBlockHash.String())
|
||||
var resyncHeight uint64
|
||||
if block.NumberU64() > L1ReorgSafeDepth+1 {
|
||||
resyncHeight = block.NumberU64() - L1ReorgSafeDepth - 1
|
||||
}
|
||||
header, err := f.client.HeaderByNumber(ctx, new(big.Int).SetUint64(resyncHeight))
|
||||
if err != nil {
|
||||
log.Error("failed to get L1 header by number", "block number", resyncHeight, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
}
|
||||
return true, resyncHeight, header.Hash(), nil, nil
|
||||
}
|
||||
lastBlockHash = block.Hash()
|
||||
}
|
||||
|
||||
return false, 0, lastBlockHash, blocks, nil
|
||||
}
|
||||
|
||||
func (f *L1FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, blocks []*types.Block) (map[uint64]uint64, []*orm.CrossMessage, error) {
|
||||
var l1RevertedTxs []*orm.CrossMessage
|
||||
blockTimestampsMap := make(map[uint64]uint64)
|
||||
|
||||
var l1FailedGatewayRouterTxs []*orm.CrossMessage
|
||||
for i := from; i <= to; i++ {
|
||||
block := blocks[i-from]
|
||||
blockTimestampsMap[block.NumberU64()] = block.Time()
|
||||
@@ -137,9 +97,7 @@ func (f *L1FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
}
|
||||
toAddress := txTo.String()
|
||||
|
||||
// GatewayRouter: L1 deposit.
|
||||
// Messenger: L1 deposit retry (replayMessage), L1 deposit refund (dropMessage), L2 withdrawal's claim (relayMessageWithProof).
|
||||
if toAddress != f.cfg.GatewayRouterAddr && toAddress != f.cfg.MessengerAddr {
|
||||
if toAddress != f.cfg.GatewayRouterAddr {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -150,7 +108,7 @@ func (f *L1FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
return nil, nil, receiptErr
|
||||
}
|
||||
|
||||
// Check if the transaction is failed
|
||||
// Check if the transaction failed
|
||||
if receipt.Status != types.ReceiptStatusFailed {
|
||||
continue
|
||||
}
|
||||
@@ -162,18 +120,18 @@ func (f *L1FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
return nil, nil, senderErr
|
||||
}
|
||||
|
||||
l1RevertedTxs = append(l1RevertedTxs, &orm.CrossMessage{
|
||||
l1FailedGatewayRouterTxs = append(l1FailedGatewayRouterTxs, &orm.CrossMessage{
|
||||
L1TxHash: tx.Hash().String(),
|
||||
MessageType: int(orm.MessageTypeL1SentMessage),
|
||||
Sender: sender.String(),
|
||||
Receiver: (*tx.To()).String(),
|
||||
L1BlockNumber: receipt.BlockNumber.Uint64(),
|
||||
BlockTimestamp: block.Time(),
|
||||
TxStatus: int(orm.TxStatusTypeSentTxReverted),
|
||||
TxStatus: int(orm.TxStatusTypeSentFailed),
|
||||
})
|
||||
}
|
||||
}
|
||||
return blockTimestampsMap, l1RevertedTxs, nil
|
||||
return blockTimestampsMap, l1FailedGatewayRouterTxs, nil
|
||||
}
|
||||
|
||||
func (f *L1FetcherLogic) l1FetcherLogs(ctx context.Context, from, to uint64) ([]types.Log, error) {
|
||||
@@ -207,110 +165,46 @@ func (f *L1FetcherLogic) l1FetcherLogs(ctx context.Context, from, to uint64) ([]
|
||||
return eventLogs, nil
|
||||
}
|
||||
|
||||
// L1Fetcher L1 fetcher
|
||||
func (f *L1FetcherLogic) L1Fetcher(ctx context.Context, from, to uint64, lastBlockHash common.Hash) (bool, uint64, common.Hash, *L1FilterResult, error) {
|
||||
// L1Fetcher l1 fetcher
|
||||
func (f *L1FetcherLogic) L1Fetcher(ctx context.Context, from, to uint64) (*L1FilterResult, error) {
|
||||
log.Info("fetch and save L1 events", "from", from, "to", to)
|
||||
|
||||
isReorg, reorgHeight, blockHash, blocks, getErr := f.getBlocksAndDetectReorg(ctx, from, to, lastBlockHash)
|
||||
if getErr != nil {
|
||||
log.Error("L1Fetcher getBlocksAndDetectReorg failed", "from", from, "to", to, "error", getErr)
|
||||
return false, 0, common.Hash{}, nil, getErr
|
||||
}
|
||||
|
||||
if isReorg {
|
||||
return isReorg, reorgHeight, blockHash, nil, nil
|
||||
}
|
||||
|
||||
blockTimestampsMap, l1RevertedTxs, err := f.getRevertedTxs(ctx, from, to, blocks)
|
||||
blockTimestampsMap, l1FailedGatewayRouterTxs, err := f.gatewayRouterFailedTxs(ctx, from, to)
|
||||
if err != nil {
|
||||
log.Error("L1Fetcher getRevertedTxs failed", "from", from, "to", to, "error", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
log.Error("L1Fetcher gatewayRouterFailedTxs failed", "from", from, "to", to, "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eventLogs, err := f.l1FetcherLogs(ctx, from, to)
|
||||
if err != nil {
|
||||
log.Error("L1Fetcher l1FetcherLogs failed", "from", from, "to", to, "error", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l1DepositMessages, l1RelayedMessages, err := f.parser.ParseL1CrossChainEventLogs(eventLogs, blockTimestampsMap)
|
||||
if err != nil {
|
||||
log.Error("failed to parse L1 cross chain event logs", "from", from, "to", to, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l1BatchEvents, err := f.parser.ParseL1BatchEventLogs(ctx, eventLogs, f.client)
|
||||
if err != nil {
|
||||
log.Error("failed to parse L1 batch event logs", "from", from, "to", to, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l1MessageQueueEvents, err := f.parser.ParseL1MessageQueueEventLogs(eventLogs, l1DepositMessages)
|
||||
l1MessageQueueEvents, err := f.parser.ParseL1MessageQueueEventLogs(eventLogs)
|
||||
if err != nil {
|
||||
log.Error("failed to parse L1 message queue event logs", "from", from, "to", to, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := L1FilterResult{
|
||||
DepositMessages: l1DepositMessages,
|
||||
RelayedMessages: l1RelayedMessages,
|
||||
BatchEvents: l1BatchEvents,
|
||||
MessageQueueEvents: l1MessageQueueEvents,
|
||||
RevertedTxs: l1RevertedTxs,
|
||||
}
|
||||
|
||||
f.updateMetrics(res)
|
||||
|
||||
return false, 0, blockHash, &res, nil
|
||||
}
|
||||
|
||||
func (f *L1FetcherLogic) updateMetrics(res L1FilterResult) {
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_failed_gateway_router_transaction").Add(float64(len(res.RevertedTxs)))
|
||||
|
||||
for _, depositMessage := range res.DepositMessages {
|
||||
switch orm.TokenType(depositMessage.TokenType) {
|
||||
case orm.TokenTypeETH:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_deposit_eth").Add(1)
|
||||
case orm.TokenTypeERC20:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_deposit_erc20").Add(1)
|
||||
case orm.TokenTypeERC721:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_deposit_erc721").Add(1)
|
||||
case orm.TokenTypeERC1155:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_deposit_erc1155").Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
for _, relayedMessage := range res.RelayedMessages {
|
||||
switch orm.TxStatusType(relayedMessage.TxStatus) {
|
||||
case orm.TxStatusTypeRelayed:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_relayed_message").Add(1)
|
||||
case orm.TxStatusTypeFailedRelayed:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_failed_relayed_message").Add(1)
|
||||
}
|
||||
// Have not tracked L1 relayed message reverted transaction yet.
|
||||
// 1. need to parse calldata of tx.
|
||||
// 2. hard to track internal tx.
|
||||
}
|
||||
|
||||
for _, batchEvent := range res.BatchEvents {
|
||||
switch orm.BatchStatusType(batchEvent.BatchStatus) {
|
||||
case orm.BatchStatusTypeCommitted:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_commit_batch_event").Add(1)
|
||||
case orm.BatchStatusTypeReverted:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_revert_batch_event").Add(1)
|
||||
case orm.BatchStatusTypeFinalized:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_finalize_batch_event").Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
for _, messageQueueEvent := range res.MessageQueueEvents {
|
||||
switch messageQueueEvent.EventType {
|
||||
case orm.MessageQueueEventTypeQueueTransaction: // sendMessage is filtered out, only leaving replayMessage or appendEnforcedTransaction.
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_replay_message_or_enforced_transaction").Add(1)
|
||||
case orm.MessageQueueEventTypeDequeueTransaction:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_skip_message").Add(1)
|
||||
case orm.MessageQueueEventTypeDropTransaction:
|
||||
f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_drop_message").Add(1)
|
||||
}
|
||||
FailedGatewayRouterTxs: l1FailedGatewayRouterTxs,
|
||||
DepositMessages: l1DepositMessages,
|
||||
RelayedMessages: l1RelayedMessages,
|
||||
BatchEvents: l1BatchEvents,
|
||||
MessageQueueEvents: l1MessageQueueEvents,
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
type L2EventParser struct {
|
||||
}
|
||||
|
||||
// NewL2EventParser creates the L2 event parser
|
||||
// NewL2EventParser create the L2 event parser
|
||||
func NewL2EventParser() *L2EventParser {
|
||||
return &L2EventParser{}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/scroll-tech/go-ethereum"
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"github.com/scroll-tech/go-ethereum/core/types"
|
||||
@@ -20,15 +18,12 @@ import (
|
||||
"scroll-tech/bridge-history-api/internal/utils"
|
||||
)
|
||||
|
||||
// L2ReorgSafeDepth represents the number of block confirmations considered safe against L2 chain reorganizations.
|
||||
// Reorganizations at this depth under normal cases are extremely unlikely.
|
||||
const L2ReorgSafeDepth = 256
|
||||
|
||||
// L2FilterResult the L2 filter result
|
||||
type L2FilterResult struct {
|
||||
WithdrawMessages []*orm.CrossMessage
|
||||
RelayedMessages []*orm.CrossMessage // relayed, failed relayed, relay tx reverted.
|
||||
OtherRevertedTxs []*orm.CrossMessage // reverted txs except relay tx reverted.
|
||||
FailedGatewayRouterTxs []*orm.CrossMessage
|
||||
RevertedRelayedMessages []*orm.CrossMessage
|
||||
WithdrawMessages []*orm.CrossMessage
|
||||
RelayedMessages []*orm.CrossMessage
|
||||
}
|
||||
|
||||
// L2FetcherLogic the L2 fetcher logic
|
||||
@@ -40,8 +35,6 @@ type L2FetcherLogic struct {
|
||||
db *gorm.DB
|
||||
crossMessageOrm *orm.CrossMessage
|
||||
batchEventOrm *orm.BatchEvent
|
||||
|
||||
l2FetcherLogicFetchedTotal *prometheus.CounterVec
|
||||
}
|
||||
|
||||
// NewL2FetcherLogic create L2 fetcher logic
|
||||
@@ -61,17 +54,15 @@ func NewL2FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.C
|
||||
}
|
||||
|
||||
// Optional erc20 gateways.
|
||||
if common.HexToAddress(cfg.USDCGatewayAddr) != (common.Address{}) {
|
||||
if cfg.USDCGatewayAddr != "" {
|
||||
addressList = append(addressList, common.HexToAddress(cfg.USDCGatewayAddr))
|
||||
}
|
||||
|
||||
if common.HexToAddress(cfg.LIDOGatewayAddr) != (common.Address{}) {
|
||||
if cfg.LIDOGatewayAddr != "" {
|
||||
addressList = append(addressList, common.HexToAddress(cfg.LIDOGatewayAddr))
|
||||
}
|
||||
|
||||
log.Info("L2 Fetcher configured with the following address list", "addresses", addressList)
|
||||
|
||||
f := &L2FetcherLogic{
|
||||
return &L2FetcherLogic{
|
||||
db: db,
|
||||
crossMessageOrm: orm.NewCrossMessage(db),
|
||||
batchEventOrm: orm.NewBatchEvent(db),
|
||||
@@ -80,48 +71,19 @@ func NewL2FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.C
|
||||
addressList: addressList,
|
||||
parser: NewL2EventParser(),
|
||||
}
|
||||
|
||||
reg := prometheus.DefaultRegisterer
|
||||
f.l2FetcherLogicFetchedTotal = promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "L2_fetcher_logic_fetched_total",
|
||||
Help: "The total number of events or failed txs fetched in L2 fetcher logic.",
|
||||
}, []string{"type"})
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *L2FetcherLogic) getBlocksAndDetectReorg(ctx context.Context, from, to uint64, lastBlockHash common.Hash) (bool, uint64, common.Hash, []*types.BlockWithRowConsumption, error) {
|
||||
func (f *L2FetcherLogic) gatewayRouterFailedTxs(ctx context.Context, from, to uint64) (map[uint64]uint64, []*orm.CrossMessage, []*orm.CrossMessage, error) {
|
||||
var l2FailedGatewayRouterTxs []*orm.CrossMessage
|
||||
var l2RevertedRelayedMessages []*orm.CrossMessage
|
||||
blockTimestampsMap := make(map[uint64]uint64)
|
||||
|
||||
blocks, err := utils.GetL2BlocksInRange(ctx, f.client, from, to)
|
||||
if err != nil {
|
||||
log.Error("failed to get L2 blocks in range", "from", from, "to", to, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
for _, block := range blocks {
|
||||
if block.ParentHash() != lastBlockHash {
|
||||
log.Warn("L2 reorg detected", "reorg height", block.NumberU64()-1, "expected hash", block.ParentHash().String(), "local hash", lastBlockHash.String())
|
||||
var resyncHeight uint64
|
||||
if block.NumberU64() > L2ReorgSafeDepth+1 {
|
||||
resyncHeight = block.NumberU64() - L2ReorgSafeDepth - 1
|
||||
}
|
||||
header, err := f.client.HeaderByNumber(ctx, new(big.Int).SetUint64(resyncHeight))
|
||||
if err != nil {
|
||||
log.Error("failed to get L2 header by number", "block number", resyncHeight, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
}
|
||||
return true, resyncHeight, header.Hash(), nil, nil
|
||||
}
|
||||
lastBlockHash = block.Hash()
|
||||
}
|
||||
|
||||
return false, 0, lastBlockHash, blocks, nil
|
||||
}
|
||||
|
||||
func (f *L2FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, blocks []*types.BlockWithRowConsumption) (map[uint64]uint64, []*orm.CrossMessage, []*orm.CrossMessage, error) {
|
||||
var l2RevertedUserTxs []*orm.CrossMessage
|
||||
var l2RevertedRelayedMessageTxs []*orm.CrossMessage
|
||||
blockTimestampsMap := make(map[uint64]uint64)
|
||||
|
||||
for i := from; i <= to; i++ {
|
||||
block := blocks[i-from]
|
||||
blockTimestampsMap[block.NumberU64()] = block.Time()
|
||||
@@ -133,7 +95,6 @@ func (f *L2FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
}
|
||||
toAddress := txTo.String()
|
||||
|
||||
// GatewayRouter: L2 withdrawal.
|
||||
if toAddress == f.cfg.GatewayRouterAddr {
|
||||
receipt, receiptErr := f.client.TransactionReceipt(ctx, tx.Hash())
|
||||
if receiptErr != nil {
|
||||
@@ -141,7 +102,7 @@ func (f *L2FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
return nil, nil, nil, receiptErr
|
||||
}
|
||||
|
||||
// Check if the transaction is failed
|
||||
// Check if the transaction failed
|
||||
if receipt.Status == types.ReceiptStatusFailed {
|
||||
signer := types.LatestSignerForChainID(new(big.Int).SetUint64(tx.ChainId().Uint64()))
|
||||
sender, signerErr := signer.Sender(tx)
|
||||
@@ -150,14 +111,14 @@ func (f *L2FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
return nil, nil, nil, signerErr
|
||||
}
|
||||
|
||||
l2RevertedUserTxs = append(l2RevertedUserTxs, &orm.CrossMessage{
|
||||
l2FailedGatewayRouterTxs = append(l2FailedGatewayRouterTxs, &orm.CrossMessage{
|
||||
L2TxHash: tx.Hash().String(),
|
||||
MessageType: int(orm.MessageTypeL2SentMessage),
|
||||
Sender: sender.String(),
|
||||
Receiver: (*tx.To()).String(),
|
||||
L2BlockNumber: receipt.BlockNumber.Uint64(),
|
||||
BlockTimestamp: block.Time(),
|
||||
TxStatus: int(orm.TxStatusTypeSentTxReverted),
|
||||
TxStatus: int(orm.TxStatusTypeSentFailed),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -169,12 +130,12 @@ func (f *L2FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
return nil, nil, nil, receiptErr
|
||||
}
|
||||
|
||||
// Check if the transaction is failed
|
||||
// Check if the transaction failed
|
||||
if receipt.Status == types.ReceiptStatusFailed {
|
||||
l2RevertedRelayedMessageTxs = append(l2RevertedRelayedMessageTxs, &orm.CrossMessage{
|
||||
MessageHash: common.BytesToHash(crypto.Keccak256(tx.AsL1MessageTx().Data)).String(),
|
||||
l2RevertedRelayedMessages = append(l2RevertedRelayedMessages, &orm.CrossMessage{
|
||||
MessageHash: "0x" + common.Bytes2Hex(crypto.Keccak256(tx.AsL1MessageTx().Data)),
|
||||
L2TxHash: tx.Hash().String(),
|
||||
TxStatus: int(orm.TxStatusTypeRelayTxReverted),
|
||||
TxStatus: int(orm.TxStatusTypeRelayedTxReverted),
|
||||
L2BlockNumber: receipt.BlockNumber.Uint64(),
|
||||
MessageType: int(orm.MessageTypeL1SentMessage),
|
||||
})
|
||||
@@ -182,7 +143,7 @@ func (f *L2FetcherLogic) getRevertedTxs(ctx context.Context, from, to uint64, bl
|
||||
}
|
||||
}
|
||||
}
|
||||
return blockTimestampsMap, l2RevertedUserTxs, l2RevertedRelayedMessageTxs, nil
|
||||
return blockTimestampsMap, l2FailedGatewayRouterTxs, l2RevertedRelayedMessages, nil
|
||||
}
|
||||
|
||||
func (f *L2FetcherLogic) l2FetcherLogs(ctx context.Context, from, to uint64) ([]types.Log, error) {
|
||||
@@ -210,72 +171,32 @@ func (f *L2FetcherLogic) l2FetcherLogs(ctx context.Context, from, to uint64) ([]
|
||||
}
|
||||
|
||||
// L2Fetcher L2 fetcher
|
||||
func (f *L2FetcherLogic) L2Fetcher(ctx context.Context, from, to uint64, lastBlockHash common.Hash) (bool, uint64, common.Hash, *L2FilterResult, error) {
|
||||
log.Info("fetch and save L2 events", "from", from, "to", to)
|
||||
func (f *L2FetcherLogic) L2Fetcher(ctx context.Context, from, to uint64) (*L2FilterResult, error) {
|
||||
log.Info("fetch and save L1 events", "from", from, "to", to)
|
||||
|
||||
isReorg, reorgHeight, blockHash, blocks, getErr := f.getBlocksAndDetectReorg(ctx, from, to, lastBlockHash)
|
||||
if getErr != nil {
|
||||
log.Error("L2Fetcher getBlocksAndDetectReorg failed", "from", from, "to", to, "error", getErr)
|
||||
return false, 0, common.Hash{}, nil, getErr
|
||||
}
|
||||
|
||||
if isReorg {
|
||||
return isReorg, reorgHeight, blockHash, nil, nil
|
||||
}
|
||||
|
||||
blockTimestampsMap, revertedUserTxs, revertedRelayMsgs, routerErr := f.getRevertedTxs(ctx, from, to, blocks)
|
||||
blockTimestampsMap, l2FailedGatewayRouterTxs, l2RevertedRelayedMessages, routerErr := f.gatewayRouterFailedTxs(ctx, from, to)
|
||||
if routerErr != nil {
|
||||
log.Error("L2Fetcher getRevertedTxs failed", "from", from, "to", to, "error", routerErr)
|
||||
return false, 0, common.Hash{}, nil, routerErr
|
||||
log.Error("L2Fetcher gatewayRouterFailedTxs failed", "from", from, "to", to, "error", routerErr)
|
||||
return nil, routerErr
|
||||
}
|
||||
|
||||
eventLogs, err := f.l2FetcherLogs(ctx, from, to)
|
||||
if err != nil {
|
||||
log.Error("L2Fetcher l2FetcherLogs failed", "from", from, "to", to, "error", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l2WithdrawMessages, l2RelayedMessages, err := f.parser.ParseL2EventLogs(eventLogs, blockTimestampsMap)
|
||||
if err != nil {
|
||||
log.Error("failed to parse L2 event logs", "from", from, "to", to, "err", err)
|
||||
return false, 0, common.Hash{}, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := L2FilterResult{
|
||||
WithdrawMessages: l2WithdrawMessages,
|
||||
RelayedMessages: append(l2RelayedMessages, revertedRelayMsgs...),
|
||||
OtherRevertedTxs: revertedUserTxs,
|
||||
}
|
||||
|
||||
f.updateMetrics(res)
|
||||
|
||||
return false, 0, blockHash, &res, nil
|
||||
}
|
||||
|
||||
func (f *L2FetcherLogic) updateMetrics(res L2FilterResult) {
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_failed_gateway_router_transaction").Add(float64(len(res.OtherRevertedTxs)))
|
||||
|
||||
for _, withdrawMessage := range res.WithdrawMessages {
|
||||
switch orm.TokenType(withdrawMessage.TokenType) {
|
||||
case orm.TokenTypeETH:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_withdraw_eth").Add(1)
|
||||
case orm.TokenTypeERC20:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_withdraw_erc20").Add(1)
|
||||
case orm.TokenTypeERC721:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_withdraw_erc721").Add(1)
|
||||
case orm.TokenTypeERC1155:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_withdraw_erc1155").Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
for _, relayedMessage := range res.RelayedMessages {
|
||||
switch orm.TxStatusType(relayedMessage.TxStatus) {
|
||||
case orm.TxStatusTypeRelayed:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_relayed_message").Add(1)
|
||||
case orm.TxStatusTypeFailedRelayed:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_failed_relayed_message").Add(1)
|
||||
case orm.TxStatusTypeRelayTxReverted:
|
||||
f.l2FetcherLogicFetchedTotal.WithLabelValues("L2_reverted_relayed_message_transaction").Add(1)
|
||||
}
|
||||
FailedGatewayRouterTxs: l2FailedGatewayRouterTxs,
|
||||
RevertedRelayedMessages: l2RevertedRelayedMessages,
|
||||
WithdrawMessages: l2WithdrawMessages,
|
||||
RelayedMessages: l2RelayedMessages,
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ type BatchEvent struct {
|
||||
|
||||
// TableName returns the table name for the BatchEvent model.
|
||||
func (*BatchEvent) TableName() string {
|
||||
return "batch_event_v2"
|
||||
return "batch_event"
|
||||
}
|
||||
|
||||
// NewBatchEvent returns a new instance of BatchEvent.
|
||||
@@ -55,7 +55,7 @@ func NewBatchEvent(db *gorm.DB) *BatchEvent {
|
||||
return &BatchEvent{db: db}
|
||||
}
|
||||
|
||||
// GetBatchEventSyncedHeightInDB returns the maximum l1_block_number from the batch_event_v2 table.
|
||||
// GetBatchEventSyncedHeightInDB returns the maximum l1_block_number from the batch_event table.
|
||||
func (c *BatchEvent) GetBatchEventSyncedHeightInDB(ctx context.Context) (uint64, error) {
|
||||
var batch BatchEvent
|
||||
db := c.db.WithContext(ctx)
|
||||
@@ -70,13 +70,12 @@ func (c *BatchEvent) GetBatchEventSyncedHeightInDB(ctx context.Context) (uint64,
|
||||
return batch.L1BlockNumber, nil
|
||||
}
|
||||
|
||||
// GetFinalizedBatchesLEBlockHeight returns the finalized batches with end block <= given block height in db.
|
||||
func (c *BatchEvent) GetFinalizedBatchesLEBlockHeight(ctx context.Context, blockHeight uint64) ([]*BatchEvent, error) {
|
||||
// GetBatchesLEBlockHeight returns the batches with end block <= given block height in db.
|
||||
func (c *BatchEvent) GetBatchesLEBlockHeight(ctx context.Context, blockHeight uint64) ([]*BatchEvent, error) {
|
||||
var batches []*BatchEvent
|
||||
db := c.db.WithContext(ctx)
|
||||
db = db.Model(&BatchEvent{})
|
||||
db = db.Where("end_block_number <= ?", blockHeight)
|
||||
db = db.Where("batch_status = ?", BatchStatusTypeFinalized)
|
||||
db = db.Where("update_status = ?", UpdateStatusTypeUnupdated)
|
||||
db = db.Order("batch_index asc")
|
||||
if err := db.Find(&batches).Error; err != nil {
|
||||
|
||||
@@ -38,21 +38,22 @@ type TxStatusType int
|
||||
|
||||
// Constants for TxStatusType.
|
||||
const (
|
||||
// TxStatusTypeSent is one of the initial statuses for cross-chain messages.
|
||||
// TxStatusTypeSent is one of the initial statuses for cross-chain messages (the other one is TxStatusTypeSentFailed).
|
||||
// It is used as the default value to prevent overwriting the transaction status in scenarios where the message status might change
|
||||
// from a later status (e.g., relayed) back to "sent".
|
||||
// Example flow (L1 -> L2 message, and L1 fetcher is slower than L2 fetcher):
|
||||
// 1. The relayed message is first tracked and processed, setting tx_status to TxStatusTypeRelayed.
|
||||
// 2. The sent message is later processed (same cross-chain message), the tx_status should not over-write TxStatusTypeRelayed.
|
||||
TxStatusTypeSent TxStatusType = iota
|
||||
TxStatusTypeSentTxReverted // Not track message hash, thus will not be processed again anymore.
|
||||
TxStatusTypeRelayed // Terminal status.
|
||||
// Example flow:
|
||||
// 1. A relayed message is processed, setting tx_status to TxStatusTypeRelayed.
|
||||
// 2. If a sent message is later processed for the same cross-chain message, the tx_status
|
||||
// should remain as TxStatusTypeRelayed and not be modified back to TxStatusTypeSent.
|
||||
TxStatusTypeSent TxStatusType = iota
|
||||
TxStatusTypeSentFailed
|
||||
TxStatusTypeRelayed
|
||||
// FailedRelayedMessage event: encoded tx failed, cannot retry. e.g., https://sepolia.scrollscan.com/tx/0xfc7d3ea5ec8dc9b664a5a886c3b33d21e665355057601033481a439498efb79a
|
||||
TxStatusTypeFailedRelayed // Terminal status.
|
||||
TxStatusTypeFailedRelayed
|
||||
// In some cases, user can retry with a larger gas limit. e.g., https://sepolia.scrollscan.com/tx/0x7323a7ba29492cb47d92206411be99b27896f2823cee0633a596b646b73f1b5b
|
||||
TxStatusTypeRelayTxReverted
|
||||
TxStatusTypeRelayedTxReverted
|
||||
TxStatusTypeSkipped
|
||||
TxStatusTypeDropped // Terminal status.
|
||||
TxStatusTypeDropped
|
||||
)
|
||||
|
||||
// RollupStatusType represents the status of a rollup.
|
||||
@@ -79,12 +80,7 @@ const (
|
||||
type MessageQueueEvent struct {
|
||||
EventType MessageQueueEventType
|
||||
QueueIndex uint64
|
||||
|
||||
// Track replay tx hash and refund tx hash.
|
||||
TxHash common.Hash
|
||||
|
||||
// QueueTransaction only in replayMessage, to track which message is replayed.
|
||||
MessageHash common.Hash
|
||||
TxHash common.Hash
|
||||
}
|
||||
|
||||
// CrossMessage represents a cross message.
|
||||
@@ -99,10 +95,8 @@ type CrossMessage struct {
|
||||
Sender string `json:"sender" gorm:"column:sender"`
|
||||
Receiver string `json:"receiver" gorm:"column:receiver"`
|
||||
MessageHash string `json:"message_hash" gorm:"column:message_hash"`
|
||||
L1TxHash string `json:"l1_tx_hash" gorm:"column:l1_tx_hash"` // initial tx hash, if MessageType is MessageTypeL1SentMessage.
|
||||
L1ReplayTxHash string `json:"l1_replay_tx_hash" gorm:"column:l1_replay_tx_hash"`
|
||||
L1RefundTxHash string `json:"l1_refund_tx_hash" gorm:"column:l1_refund_tx_hash"`
|
||||
L2TxHash string `json:"l2_tx_hash" gorm:"column:l2_tx_hash"` // initial tx hash, if MessageType is MessageTypeL2SentMessage.
|
||||
L1TxHash string `json:"l1_tx_hash" gorm:"column:l1_tx_hash"`
|
||||
L2TxHash string `json:"l2_tx_hash" gorm:"column:l2_tx_hash"`
|
||||
L1BlockNumber uint64 `json:"l1_block_number" gorm:"column:l1_block_number"`
|
||||
L2BlockNumber uint64 `json:"l2_block_number" gorm:"column:l2_block_number"`
|
||||
L1TokenAddress string `json:"l1_token_address" gorm:"column:l1_token_address"`
|
||||
@@ -124,7 +118,7 @@ type CrossMessage struct {
|
||||
|
||||
// TableName returns the table name for the CrossMessage model.
|
||||
func (*CrossMessage) TableName() string {
|
||||
return "cross_message_v2"
|
||||
return "cross_message"
|
||||
}
|
||||
|
||||
// NewCrossMessage returns a new instance of CrossMessage.
|
||||
@@ -160,42 +154,23 @@ func (c *CrossMessage) GetMessageSyncedHeightInDB(ctx context.Context, messageTy
|
||||
}
|
||||
}
|
||||
|
||||
// GetL2LatestFinalizedWithdrawal returns the latest finalized L2 withdrawal from the database.
|
||||
func (c *CrossMessage) GetL2LatestFinalizedWithdrawal(ctx context.Context) (*CrossMessage, error) {
|
||||
// GetLatestL2Withdrawal returns the latest processed L2 withdrawal from the database.
|
||||
func (c *CrossMessage) GetLatestL2Withdrawal(ctx context.Context) (*CrossMessage, error) {
|
||||
var message CrossMessage
|
||||
db := c.db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
db = db.Where("message_type = ?", MessageTypeL2SentMessage)
|
||||
db = db.Where("rollup_status = ?", RollupStatusTypeFinalized)
|
||||
db = db.Where("tx_status != ?", TxStatusTypeSentFailed)
|
||||
db = db.Order("message_nonce desc")
|
||||
if err := db.First(&message).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get latest L2 finalized sent message event, error: %w", err)
|
||||
return nil, fmt.Errorf("failed to get latest L2 sent message event, error: %w", err)
|
||||
}
|
||||
return &message, nil
|
||||
}
|
||||
|
||||
// GetL2WithdrawalsByBlockRange returns the L2 withdrawals by block range from the database.
|
||||
func (c *CrossMessage) GetL2WithdrawalsByBlockRange(ctx context.Context, startBlock, endBlock uint64) ([]*CrossMessage, error) {
|
||||
var messages []*CrossMessage
|
||||
db := c.db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
db = db.Where("l2_block_number >= ?", startBlock)
|
||||
db = db.Where("l2_block_number <= ?", endBlock)
|
||||
db = db.Where("tx_status != ?", TxStatusTypeSentTxReverted)
|
||||
db = db.Where("message_type = ?", MessageTypeL2SentMessage)
|
||||
db = db.Order("message_nonce asc")
|
||||
if err := db.Find(&messages).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get latest L2 finalized sent message event, error: %w", err)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// GetMessagesByTxHashes retrieves all cross messages from the database that match the provided transaction hashes.
|
||||
func (c *CrossMessage) GetMessagesByTxHashes(ctx context.Context, txHashes []string) ([]*CrossMessage, error) {
|
||||
var messages []*CrossMessage
|
||||
@@ -255,7 +230,6 @@ func (c *CrossMessage) GetTxsByAddress(ctx context.Context, sender string) ([]*C
|
||||
|
||||
// UpdateL1MessageQueueEventsInfo updates the information about L1 message queue events in the database.
|
||||
func (c *CrossMessage) UpdateL1MessageQueueEventsInfo(ctx context.Context, l1MessageQueueEvents []*MessageQueueEvent, dbTX ...*gorm.DB) error {
|
||||
// update tx statuses.
|
||||
for _, l1MessageQueueEvent := range l1MessageQueueEvents {
|
||||
db := c.db
|
||||
if len(dbTX) > 0 && dbTX[0] != nil {
|
||||
@@ -263,62 +237,20 @@ func (c *CrossMessage) UpdateL1MessageQueueEventsInfo(ctx context.Context, l1Mes
|
||||
}
|
||||
db = db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
// do not over-write terminal statuses.
|
||||
db = db.Where("tx_status != ?", TxStatusTypeRelayed)
|
||||
db = db.Where("tx_status != ?", TxStatusTypeFailedRelayed)
|
||||
db = db.Where("tx_status != ?", TxStatusTypeDropped)
|
||||
txStatusUpdateFields := make(map[string]interface{})
|
||||
db = db.Where("message_type = ?", MessageTypeL1SentMessage)
|
||||
db = db.Where("message_nonce = ?", l1MessageQueueEvent.QueueIndex)
|
||||
updateFields := make(map[string]interface{})
|
||||
switch l1MessageQueueEvent.EventType {
|
||||
case MessageQueueEventTypeQueueTransaction:
|
||||
// only replayMessages or enforced txs (whose message hashes would not be found), sentMessages have been filtered out.
|
||||
// replayMessage case:
|
||||
// First SentMessage in L1: https://sepolia.etherscan.io/tx/0xbee4b631312448fcc2caac86e4dccf0a2ae0a88acd6c5fd8764d39d746e472eb
|
||||
// Transaction reverted in L2: https://sepolia.scrollscan.com/tx/0xde6ef307a7da255888aad7a4c40a6b8c886e46a8a05883070bbf18b736cbfb8c
|
||||
// replayMessage: https://sepolia.etherscan.io/tx/0xa5392891232bb32d98fcdbaca0d91b4d22ef2755380d07d982eebd47b147ce28
|
||||
//
|
||||
// Note: update l1_tx_hash if the user calls replayMessage, cannot use queue index here,
|
||||
// because in replayMessage, queue index != message nonce.
|
||||
// Ref: https://github.com/scroll-tech/scroll/blob/v4.3.44/contracts/src/L1/L1ScrollMessenger.sol#L187-L190
|
||||
db = db.Where("message_hash = ?", l1MessageQueueEvent.MessageHash.String())
|
||||
txStatusUpdateFields["tx_status"] = TxStatusTypeSent // reset status to "sent".
|
||||
// Update l1_tx_hash if the user calls replayMessage.
|
||||
updateFields["l1_tx_hash"] = l1MessageQueueEvent.TxHash.String()
|
||||
case MessageQueueEventTypeDequeueTransaction:
|
||||
db = db.Where("message_nonce = ?", l1MessageQueueEvent.QueueIndex)
|
||||
db = db.Where("message_type = ?", MessageTypeL1SentMessage)
|
||||
txStatusUpdateFields["tx_status"] = TxStatusTypeSkipped
|
||||
updateFields["tx_status"] = TxStatusTypeSkipped
|
||||
case MessageQueueEventTypeDropTransaction:
|
||||
db = db.Where("message_nonce = ?", l1MessageQueueEvent.QueueIndex)
|
||||
db = db.Where("message_type = ?", MessageTypeL1SentMessage)
|
||||
txStatusUpdateFields["tx_status"] = TxStatusTypeDropped
|
||||
updateFields["tx_status"] = TxStatusTypeDropped
|
||||
}
|
||||
if err := db.Updates(txStatusUpdateFields).Error; err != nil {
|
||||
return fmt.Errorf("failed to update tx statuses of L1 message queue events, update fields: %v, error: %w", txStatusUpdateFields, err)
|
||||
}
|
||||
}
|
||||
|
||||
// update tx hashes of replay and refund.
|
||||
for _, l1MessageQueueEvent := range l1MessageQueueEvents {
|
||||
db := c.db
|
||||
if len(dbTX) > 0 && dbTX[0] != nil {
|
||||
db = dbTX[0]
|
||||
}
|
||||
db = db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
txHashUpdateFields := make(map[string]interface{})
|
||||
switch l1MessageQueueEvent.EventType {
|
||||
case MessageQueueEventTypeQueueTransaction:
|
||||
// only replayMessages or enforced txs (whose message hashes would not be found), sentMessages have been filtered out.
|
||||
db = db.Where("message_hash = ?", l1MessageQueueEvent.MessageHash.String())
|
||||
txHashUpdateFields["l1_replay_tx_hash"] = l1MessageQueueEvent.TxHash.String()
|
||||
case MessageQueueEventTypeDropTransaction:
|
||||
db = db.Where("message_nonce = ?", l1MessageQueueEvent.QueueIndex)
|
||||
db = db.Where("message_type = ?", MessageTypeL1SentMessage)
|
||||
txHashUpdateFields["l1_refund_tx_hash"] = l1MessageQueueEvent.TxHash.String()
|
||||
}
|
||||
// Check if there are fields to update to avoid empty update operation (skip message).
|
||||
if len(txHashUpdateFields) > 0 {
|
||||
if err := db.Updates(txHashUpdateFields).Error; err != nil {
|
||||
return fmt.Errorf("failed to update tx hashes of replay and refund in L1 message queue events info, update fields: %v, error: %w", txHashUpdateFields, err)
|
||||
}
|
||||
if err := db.Updates(updateFields).Error; err != nil {
|
||||
return fmt.Errorf("failed to update L1 message queue events info, error: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -340,27 +272,6 @@ func (c *CrossMessage) UpdateBatchStatusOfL2Withdrawals(ctx context.Context, sta
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateBatchIndexRollupStatusMerkleProofOfL2Messages updates the batch_index, rollup_status, and merkle_proof fields for a list of L2 cross messages.
|
||||
func (c *CrossMessage) UpdateBatchIndexRollupStatusMerkleProofOfL2Messages(ctx context.Context, messages []*CrossMessage) error {
|
||||
if len(messages) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, message := range messages {
|
||||
updateFields := map[string]interface{}{
|
||||
"batch_index": message.BatchIndex,
|
||||
"rollup_status": message.RollupStatus,
|
||||
"merkle_proof": message.MerkleProof,
|
||||
}
|
||||
db := c.db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
db = db.Where("message_hash = ?", message.MessageHash)
|
||||
if err := db.Updates(updateFields).Error; err != nil {
|
||||
return fmt.Errorf("failed to update L2 message with message_hash %s, error: %w", message.MessageHash, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertOrUpdateL1Messages inserts or updates a list of L1 cross messages into the database.
|
||||
func (c *CrossMessage) InsertOrUpdateL1Messages(ctx context.Context, messages []*CrossMessage, dbTX ...*gorm.DB) error {
|
||||
if len(messages) == 0 {
|
||||
@@ -395,10 +306,9 @@ func (c *CrossMessage) InsertOrUpdateL2Messages(ctx context.Context, messages []
|
||||
db = db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
// 'tx_status' column is not explicitly assigned during the update to prevent a later status from being overwritten back to "sent".
|
||||
// The merkle_proof is updated separately in batch status updates and hence is not included here.
|
||||
db = db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "message_hash"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"sender", "receiver", "token_type", "l2_block_number", "l2_tx_hash", "l1_token_address", "l2_token_address", "token_ids", "token_amounts", "message_type", "block_timestamp", "message_from", "message_to", "message_value", "message_data", "message_nonce"}),
|
||||
DoUpdates: clause.AssignmentColumns([]string{"sender", "receiver", "token_type", "l2_block_number", "l2_tx_hash", "l1_token_address", "l2_token_address", "token_ids", "token_amounts", "message_type", "block_timestamp", "message_from", "message_to", "message_value", "message_data", "merkle_proof", "message_nonce"}),
|
||||
})
|
||||
if err := db.Create(messages).Error; err != nil {
|
||||
return fmt.Errorf("failed to insert message, error: %w", err)
|
||||
@@ -434,35 +344,24 @@ func (c *CrossMessage) InsertOrUpdateL2RelayedMessagesOfL1Deposits(ctx context.C
|
||||
if len(l2RelayedMessages) == 0 {
|
||||
return nil
|
||||
}
|
||||
// Deduplicate messages, for each message_hash, retaining message with the highest block number.
|
||||
// This is necessary as a single message, like a FailedRelayedMessage or a reverted relayed transaction,
|
||||
// may be relayed multiple times within certain block ranges, potentially leading to the error:
|
||||
// "ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time (SQLSTATE 21000)".
|
||||
// This happens if we attempt to insert multiple records with the same message_hash in a single db.Create operation.
|
||||
// For example, see these transactions where the same message was relayed twice within certain block ranges:
|
||||
// Reverted tx 1: https://sepolia.scrollscan.com/tx/0xcd6979277c3bc747445273a5e58ef1e9692fbe101d88cfefbbb69d3aef3193c0
|
||||
// Reverted tx 2: https://sepolia.scrollscan.com/tx/0x43e28ed7cb71107c18c5d8ebbdb4a1d9cac73e60391d14d41e92985028faa337
|
||||
// Another example:
|
||||
// FailedRelayedMessage 1: https://sepolia.scrollscan.com/tx/0xfadb147fb211e5096446c5cac3ae0a8a705d2ece6c47c65135c8874f84638f17
|
||||
// FailedRelayedMessage 2: https://sepolia.scrollscan.com/tx/0x6cb149b61afd07bf2e17561a59ebebde41e343b6610290c97515b2f862160b42
|
||||
mergedL2RelayedMessages := make(map[string]*CrossMessage)
|
||||
for _, message := range l2RelayedMessages {
|
||||
if existing, found := mergedL2RelayedMessages[message.MessageHash]; found {
|
||||
if TxStatusType(message.TxStatus) == TxStatusTypeRelayed || message.L2BlockNumber > existing.L2BlockNumber {
|
||||
mergedL2RelayedMessages[message.MessageHash] = message
|
||||
}
|
||||
} else {
|
||||
mergedL2RelayedMessages[message.MessageHash] = message
|
||||
}
|
||||
db := c.db.WithContext(ctx)
|
||||
db = db.Model(&CrossMessage{})
|
||||
db = db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "message_hash"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"message_type", "l2_block_number", "l2_tx_hash", "tx_status"}),
|
||||
})
|
||||
if err := db.Create(l2RelayedMessages).Error; err != nil {
|
||||
return fmt.Errorf("failed to update L2 relayed message of L1 deposit, error: %w", err)
|
||||
}
|
||||
uniqueL2RelayedMessages := make([]*CrossMessage, 0, len(mergedL2RelayedMessages))
|
||||
for _, msg := range mergedL2RelayedMessages {
|
||||
uniqueL2RelayedMessages = append(uniqueL2RelayedMessages, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertOrUpdateL2RevertedRelayedMessagesOfL1Deposits inserts or updates the database with a list of L2 relayed messages related to L1 deposits.
|
||||
func (c *CrossMessage) InsertOrUpdateL2RevertedRelayedMessagesOfL1Deposits(ctx context.Context, l2RevertedRelayedMessages []*CrossMessage, dbTX ...*gorm.DB) error {
|
||||
if len(l2RevertedRelayedMessages) == 0 {
|
||||
return nil
|
||||
}
|
||||
// Do not update tx status of successfully or failed relayed messages,
|
||||
// because if a message is handled, the later relayed message tx would be reverted.
|
||||
// ref: https://github.com/scroll-tech/scroll/blob/v4.3.44/contracts/src/L2/L2ScrollMessenger.sol#L102
|
||||
// e.g.,
|
||||
// Do not update tx status of successfully relayed messages. e.g.,
|
||||
// Successfully relayed: https://sepolia.scrollscan.com/tx/0x4eb7cb07ba76956259c0079819a34a146f8a93dd891dc94812e9b3d66b056ec7#eventlog
|
||||
// Reverted tx 1 (Reason: Message was already successfully executed): https://sepolia.scrollscan.com/tx/0x1973cafa14eb40734df30da7bfd4d9aceb53f8f26e09d96198c16d0e2e4a95fd
|
||||
// Reverted tx 2 (Reason: Message was already successfully executed): https://sepolia.scrollscan.com/tx/0x02fc3a28684a590aead2482022f56281539085bd3d273ac8dedc1ceccb2bc554
|
||||
@@ -471,18 +370,9 @@ func (c *CrossMessage) InsertOrUpdateL2RelayedMessagesOfL1Deposits(ctx context.C
|
||||
db = db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "message_hash"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"message_type", "l2_block_number", "l2_tx_hash", "tx_status"}),
|
||||
Where: clause.Where{
|
||||
Exprs: []clause.Expression{
|
||||
clause.And(
|
||||
// do not over-write terminal statuses.
|
||||
clause.Neq{Column: "cross_message_v2.tx_status", Value: TxStatusTypeRelayed},
|
||||
clause.Neq{Column: "cross_message_v2.tx_status", Value: TxStatusTypeFailedRelayed},
|
||||
clause.Neq{Column: "cross_message_v2.tx_status", Value: TxStatusTypeDropped},
|
||||
),
|
||||
},
|
||||
},
|
||||
Where: clause.Where{Exprs: []clause.Expression{clause.Neq{Column: "cross_message.tx_status", Value: TxStatusTypeRelayed}}},
|
||||
})
|
||||
if err := db.Create(uniqueL2RelayedMessages).Error; err != nil {
|
||||
if err := db.Create(l2RevertedRelayedMessages).Error; err != nil {
|
||||
return fmt.Errorf("failed to update L2 reverted relayed message of L1 deposit, error: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -501,13 +391,10 @@ func (c *CrossMessage) InsertOrUpdateL1RelayedMessagesOfL2Withdrawals(ctx contex
|
||||
// For example, see these transactions where the same message was relayed twice within certain block ranges:
|
||||
// FailedRelayedMessage 1: https://sepolia.etherscan.io/tx/0x28b3212cda6ca0f3790f362a780257bbe2b37417ccf75a4eca6c3a08294c8f1b#eventlog
|
||||
// FailedRelayedMessage 2: https://sepolia.etherscan.io/tx/0xc8a8254825dd2cab5caef58cfd8d88c077ceadadc78f2340214a86cf8ab88543#eventlog
|
||||
// Another example (relayed success, then relayed again):
|
||||
// Relay Message, and success: https://sepolia.etherscan.io/tx/0xcfdf2f5446719e3e123a8aa06e4d6b3809c3850a13adf875755c8b1e423aa448#eventlog
|
||||
// Relay Message again, and reverted: https://sepolia.etherscan.io/tx/0xb1fcae7546f3de4cfd0b4d679f4075adb4eb69578b12e2b5673f5f24b1836578
|
||||
mergedL1RelayedMessages := make(map[string]*CrossMessage)
|
||||
for _, message := range l1RelayedMessages {
|
||||
if existing, found := mergedL1RelayedMessages[message.MessageHash]; found {
|
||||
if TxStatusType(message.TxStatus) == TxStatusTypeRelayed || message.L1BlockNumber > existing.L1BlockNumber {
|
||||
if message.L1BlockNumber > existing.L1BlockNumber {
|
||||
mergedL1RelayedMessages[message.MessageHash] = message
|
||||
}
|
||||
} else {
|
||||
@@ -527,16 +414,6 @@ func (c *CrossMessage) InsertOrUpdateL1RelayedMessagesOfL2Withdrawals(ctx contex
|
||||
db = db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "message_hash"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"message_type", "l1_block_number", "l1_tx_hash", "tx_status"}),
|
||||
Where: clause.Where{
|
||||
Exprs: []clause.Expression{
|
||||
clause.And(
|
||||
// do not over-write terminal statuses.
|
||||
clause.Neq{Column: "cross_message_v2.tx_status", Value: TxStatusTypeRelayed},
|
||||
clause.Neq{Column: "cross_message_v2.tx_status", Value: TxStatusTypeFailedRelayed},
|
||||
clause.Neq{Column: "cross_message_v2.tx_status", Value: TxStatusTypeDropped},
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err := db.Create(uniqueL1RelayedMessages).Error; err != nil {
|
||||
return fmt.Errorf("failed to update L1 relayed message of L2 withdrawal, error: %w", err)
|
||||
|
||||
@@ -18,7 +18,7 @@ const MigrationsDir string = "migrations"
|
||||
func init() {
|
||||
goose.SetBaseFS(embedMigrations)
|
||||
goose.SetSequential(true)
|
||||
goose.SetTableName("bridge_historyv2_migrations")
|
||||
goose.SetTableName("bridge_history_migrations")
|
||||
|
||||
verbose, _ := strconv.ParseBool(os.Getenv("LOG_SQL_MIGRATIONS"))
|
||||
goose.SetVerbose(verbose)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE cross_message_v2
|
||||
CREATE TABLE cross_message
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
message_type SMALLINT NOT NULL,
|
||||
@@ -12,8 +12,6 @@ CREATE TABLE cross_message_v2
|
||||
|
||||
message_hash VARCHAR DEFAULT NULL, -- NULL for failed txs
|
||||
l1_tx_hash VARCHAR DEFAULT NULL,
|
||||
l1_replay_tx_hash VARCHAR DEFAULT NULL,
|
||||
l1_refund_tx_hash VARCHAR DEFAULT NULL,
|
||||
l2_tx_hash VARCHAR DEFAULT NULL,
|
||||
l1_block_number BIGINT DEFAULT NULL,
|
||||
l2_block_number BIGINT DEFAULT NULL,
|
||||
@@ -38,20 +36,19 @@ CREATE TABLE cross_message_v2
|
||||
deleted_at TIMESTAMP(0) DEFAULT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_cm_message_hash ON cross_message_v2 (message_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_l1_block_number ON cross_message_v2 (message_type, l1_block_number DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_l2_block_number ON cross_message_v2 (message_type, l2_block_number DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_rollup_status_message_nonce ON cross_message_v2 (message_type, rollup_status, message_nonce DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_message_nonce_tx_status_l2_block_number ON cross_message_v2 (message_type, message_nonce, tx_status, l2_block_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_l1_tx_hash ON cross_message_v2 (l1_tx_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_l2_tx_hash ON cross_message_v2 (l2_tx_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_tx_status_sender_block_timestamp ON cross_message_v2 (message_type, tx_status, sender, block_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_sender_block_timestamp ON cross_message_v2 (message_type, sender, block_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_sender_block_timestamp ON cross_message_v2 (sender, block_timestamp DESC);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_cm_message_hash ON cross_message (message_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_l1_block_number ON cross_message (message_type, l1_block_number DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_l2_block_number ON cross_message (message_type, l2_block_number DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_message_nonce ON cross_message (message_type, message_nonce DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_l1_tx_hash ON cross_message (l1_tx_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_l2_tx_hash ON cross_message (l2_tx_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_tx_status_sender_block_timestamp ON cross_message (message_type, tx_status, sender, block_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_message_type_sender_block_timestamp ON cross_message (message_type, sender, block_timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_cm_sender_block_timestamp ON cross_message (sender, block_timestamp DESC);
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS cross_message_v2;
|
||||
DROP TABLE IF EXISTS cross_message;
|
||||
-- +goose StatementEnd
|
||||
@@ -1,6 +1,6 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE batch_event_v2
|
||||
CREATE TABLE batch_event
|
||||
(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
l1_block_number BIGINT NOT NULL,
|
||||
@@ -15,14 +15,14 @@ CREATE TABLE batch_event_v2
|
||||
deleted_at TIMESTAMP(0) DEFAULT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_be_l1_block_number ON batch_event_v2 (l1_block_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_be_batch_index ON batch_event_v2 (batch_index);
|
||||
CREATE INDEX IF NOT EXISTS idx_be_batch_index_batch_hash ON batch_event_v2 (batch_index, batch_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_be_end_block_number_update_status_batch_status_batch_index ON batch_event_v2 (end_block_number, update_status, batch_status, batch_index);
|
||||
CREATE INDEX IF NOT EXISTS idx_be_l1_block_number ON batch_event (l1_block_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_be_batch_index ON batch_event (batch_index);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS unique_idx_be_batch_index_batch_hash ON batch_event (batch_index, batch_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_be_end_block_number_update_status_batch_index ON batch_event (end_block_number, update_status, batch_index);
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS batch_event_v2;
|
||||
DROP TABLE IF EXISTS batch_event;
|
||||
-- +goose StatementEnd
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"scroll-tech/bridge-history-api/internal/orm"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -39,8 +37,8 @@ type QueryByHashRequest struct {
|
||||
|
||||
// ResultData contains return txs and total
|
||||
type ResultData struct {
|
||||
Results []*TxHistoryInfo `json:"results"`
|
||||
Total uint64 `json:"total"`
|
||||
Result []*TxHistoryInfo `json:"result"`
|
||||
Total uint64 `json:"total"`
|
||||
}
|
||||
|
||||
// Response the response schema
|
||||
@@ -50,46 +48,37 @@ type Response struct {
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// CounterpartChainTx is the schema of counterpart chain tx info
|
||||
type CounterpartChainTx struct {
|
||||
// Finalized the schema of tx finalized infos
|
||||
type Finalized struct {
|
||||
Hash string `json:"hash"`
|
||||
BlockNumber uint64 `json:"block_number"`
|
||||
BlockNumber uint64 `json:"blockNumber"`
|
||||
}
|
||||
|
||||
// ClaimInfo is the schema of tx claim info
|
||||
type ClaimInfo struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
Value string `json:"value"`
|
||||
Nonce string `json:"nonce"`
|
||||
Message string `json:"message"`
|
||||
Proof L2MessageProof `json:"proof"`
|
||||
Claimable bool `json:"claimable"`
|
||||
}
|
||||
|
||||
// L2MessageProof is the schema of L2 message proof
|
||||
type L2MessageProof struct {
|
||||
BatchIndex string `json:"batch_index"`
|
||||
MerkleProof string `json:"merkle_proof"`
|
||||
// UserClaimInfo the schema of tx claim infos
|
||||
type UserClaimInfo struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
Value string `json:"value"`
|
||||
Nonce string `json:"nonce"`
|
||||
Message string `json:"message"`
|
||||
Proof string `json:"proof"`
|
||||
BatchIndex string `json:"batch_index"`
|
||||
Claimable bool `json:"claimable"`
|
||||
}
|
||||
|
||||
// TxHistoryInfo the schema of tx history infos
|
||||
type TxHistoryInfo struct {
|
||||
Hash string `json:"hash"`
|
||||
ReplayTxHash string `json:"replay_tx_hash"`
|
||||
RefundTxHash string `json:"refund_tx_hash"`
|
||||
MessageHash string `json:"message_hash"`
|
||||
TokenType orm.TokenType `json:"token_type"` // 0: unknown, 1: eth, 2: erc20, 3: erc721, 4: erc1155
|
||||
TokenIDs []string `json:"token_ids"` // only for erc721 and erc1155
|
||||
TokenAmounts []string `json:"token_amounts"` // for eth and erc20, the length is 1, for erc721 and erc1155, the length could be > 1
|
||||
MessageType orm.MessageType `json:"message_type"` // 0: unknown, 1: layer 1 message, 2: layer 2 message
|
||||
L1TokenAddress string `json:"l1_token_address"`
|
||||
L2TokenAddress string `json:"l2_token_address"`
|
||||
BlockNumber uint64 `json:"block_number"`
|
||||
TxStatus orm.TxStatusType `json:"tx_status"` // 0: sent, 1: sent failed, 2: relayed, 3: failed relayed, 4: relayed reverted, 5: skipped, 6: dropped
|
||||
CounterpartChainTx *CounterpartChainTx `json:"counterpart_chain_tx"`
|
||||
ClaimInfo *ClaimInfo `json:"claim_info"`
|
||||
BlockTimestamp uint64 `json:"block_timestamp"`
|
||||
Hash string `json:"hash"`
|
||||
MsgHash string `json:"msgHash"`
|
||||
Amount string `json:"amount"`
|
||||
IsL1 bool `json:"isL1"`
|
||||
L1Token string `json:"l1Token"`
|
||||
L2Token string `json:"l2Token"`
|
||||
BlockNumber uint64 `json:"blockNumber"`
|
||||
TxStatus int `json:"txStatus"`
|
||||
FinalizeTx *Finalized `json:"finalizeTx"`
|
||||
ClaimInfo *UserClaimInfo `json:"claimInfo"`
|
||||
BlockTimestamp uint64 `json:"blockTimestamp"`
|
||||
}
|
||||
|
||||
// RenderJSON renders response with json
|
||||
|
||||
@@ -191,19 +191,7 @@ func ConvertBigIntArrayToString(array []*big.Int) string {
|
||||
return result
|
||||
}
|
||||
|
||||
// ConvertStringToStringArray takes a string with values separated by commas and returns a slice of strings
|
||||
func ConvertStringToStringArray(s string) []string {
|
||||
if s == "" {
|
||||
return []string{}
|
||||
}
|
||||
stringParts := strings.Split(s, ",")
|
||||
for i, part := range stringParts {
|
||||
stringParts[i] = strings.TrimSpace(part)
|
||||
}
|
||||
return stringParts
|
||||
}
|
||||
|
||||
// GetSkippedQueueIndices gets the skipped queue indices
|
||||
// GetSkippedQueueIndices get the skipped queue indices
|
||||
func GetSkippedQueueIndices(startIndex uint64, skippedBitmap *big.Int) []uint64 {
|
||||
var indices []uint64
|
||||
for i := 0; i < 256; i++ {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
@@ -37,55 +36,3 @@ func TestGetBatchRangeFromCalldata(t *testing.T) {
|
||||
assert.Equal(t, start, uint64(0))
|
||||
assert.Equal(t, finish, uint64(0))
|
||||
}
|
||||
|
||||
// TestConvertBigIntArrayToString tests the ConvertBigIntArrayToString function
|
||||
func TestConvertBigIntArrayToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
array []*big.Int
|
||||
expected string
|
||||
}{
|
||||
{[]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, "1, 2, 3"},
|
||||
{[]*big.Int{big.NewInt(0), big.NewInt(-1)}, "0, -1"},
|
||||
{[]*big.Int{}, ""},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
got := ConvertBigIntArrayToString(test.array)
|
||||
assert.Equal(t, test.expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestConvertStringToStringArray tests the ConvertStringToStringArray function
|
||||
func TestConvertStringToStringArray(t *testing.T) {
|
||||
tests := []struct {
|
||||
s string
|
||||
expected []string
|
||||
}{
|
||||
{"1, 2, 3", []string{"1", "2", "3"}},
|
||||
{" 4 , 5 , 6 ", []string{"4", "5", "6"}},
|
||||
{"", []string{}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
got := ConvertStringToStringArray(test.s)
|
||||
assert.Equal(t, test.expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetSkippedQueueIndices tests the GetSkippedQueueIndices function
|
||||
func TestGetSkippedQueueIndices(t *testing.T) {
|
||||
tests := []struct {
|
||||
startIndex uint64
|
||||
bitmap *big.Int
|
||||
expected []uint64
|
||||
}{
|
||||
{0, big.NewInt(0b101), []uint64{0, 2}},
|
||||
{10, big.NewInt(0b110), []uint64{11, 12}},
|
||||
{0, big.NewInt(0), nil}, // No bits set
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
got := GetSkippedQueueIndices(test.startIndex, test.bitmap)
|
||||
assert.Equal(t, test.expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,71 +46,15 @@ func (w *WithdrawTrie) Initialize(currentMessageNonce uint64, msgHash common.Has
|
||||
}
|
||||
|
||||
// AppendMessages appends a list of new messages as leaf nodes to the rightest of the tree and returns the proofs for all messages.
|
||||
// The function correctly returns the proofs for the entire tree after all messages have been inserted, not the individual proofs after each insertion.
|
||||
func (w *WithdrawTrie) AppendMessages(hashes []common.Hash) [][]byte {
|
||||
length := len(hashes)
|
||||
if length == 0 {
|
||||
return make([][]byte, 0)
|
||||
}
|
||||
|
||||
cache := make([]map[uint64]common.Hash, MaxHeight)
|
||||
for h := 0; h < MaxHeight; h++ {
|
||||
cache[h] = make(map[uint64]common.Hash)
|
||||
}
|
||||
|
||||
// cache all branches will be used later.
|
||||
if w.NextMessageNonce != 0 {
|
||||
index := w.NextMessageNonce
|
||||
for h := 0; h <= w.height; h++ {
|
||||
if index%2 == 1 {
|
||||
// right child, `w.branches[h]` is the corresponding left child
|
||||
// the index of left child should be `index ^ 1`.
|
||||
cache[h][index^1] = w.branches[h]
|
||||
}
|
||||
index >>= 1
|
||||
}
|
||||
}
|
||||
// cache all new leaves
|
||||
for i := 0; i < length; i++ {
|
||||
cache[0][w.NextMessageNonce+uint64(i)] = hashes[i]
|
||||
}
|
||||
|
||||
// build withdraw trie with new hashes
|
||||
minIndex := w.NextMessageNonce
|
||||
maxIndex := w.NextMessageNonce + uint64(length) - 1
|
||||
for h := 0; maxIndex > 0; h++ {
|
||||
if minIndex%2 == 1 {
|
||||
minIndex--
|
||||
}
|
||||
if maxIndex%2 == 0 {
|
||||
cache[h][maxIndex^1] = w.zeroes[h]
|
||||
}
|
||||
for i := minIndex; i <= maxIndex; i += 2 {
|
||||
cache[h+1][i>>1] = Keccak2(cache[h][i], cache[h][i^1])
|
||||
}
|
||||
minIndex >>= 1
|
||||
maxIndex >>= 1
|
||||
}
|
||||
|
||||
// update branches using hashes one by one
|
||||
for i := 0; i < length; i++ {
|
||||
proof := updateBranchWithNewMessage(w.zeroes, w.branches, w.NextMessageNonce, hashes[i])
|
||||
w.NextMessageNonce++
|
||||
w.height = len(proof)
|
||||
}
|
||||
|
||||
proofs := make([][]byte, length)
|
||||
// retrieve merkle proof from cache
|
||||
for i := 0; i < length; i++ {
|
||||
index := w.NextMessageNonce + uint64(i) - uint64(length)
|
||||
var merkleProof []common.Hash
|
||||
for h := 0; h < w.height; h++ {
|
||||
merkleProof = append(merkleProof, cache[h][index^1])
|
||||
index >>= 1
|
||||
}
|
||||
merkleProof := updateBranchWithNewMessage(w.zeroes, w.branches, w.NextMessageNonce, hashes[i])
|
||||
w.NextMessageNonce++
|
||||
w.height = len(merkleProof)
|
||||
proofs[i] = encodeMerkleProofToBytes(merkleProof)
|
||||
}
|
||||
|
||||
return proofs
|
||||
}
|
||||
|
||||
|
||||
@@ -17,5 +17,5 @@ RUN --mount=target=. \
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/bridgehistoryapi-api /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["bridgehistoryapi-api"]
|
||||
@@ -14,6 +14,7 @@ RUN --mount=target=. \
|
||||
|
||||
# Pull db_cli into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/db_cli /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["db_cli"]
|
||||
@@ -17,5 +17,5 @@ RUN --mount=target=. \
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/bridgehistoryapi-fetcher /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["bridgehistoryapi-fetcher"]
|
||||
@@ -46,5 +46,5 @@ RUN mkdir -p /src/coordinator/internal/logic/verifier/lib
|
||||
COPY --from=builder /bin/lib /src/coordinator/internal/logic/verifier/lib
|
||||
COPY --from=builder /bin/coordinator_api /bin/
|
||||
RUN /bin/coordinator_api --version
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["/bin/coordinator_api"]
|
||||
|
||||
@@ -21,5 +21,5 @@ RUN --mount=target=. \
|
||||
# Pull coordinator into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
COPY --from=builder /bin/coordinator_cron /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["coordinator_cron"]
|
||||
@@ -21,6 +21,7 @@ RUN --mount=target=. \
|
||||
|
||||
# Pull db_cli into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/db_cli /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["db_cli"]
|
||||
|
||||
@@ -21,6 +21,7 @@ RUN --mount=target=. \
|
||||
|
||||
# Pull event_watcher into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/event_watcher /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["event_watcher"]
|
||||
@@ -21,6 +21,7 @@ RUN --mount=target=. \
|
||||
|
||||
# Pull gas_oracle into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/gas_oracle /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["gas_oracle"]
|
||||
@@ -21,6 +21,7 @@ RUN --mount=target=. \
|
||||
|
||||
# Pull rollup_relayer into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
||||
COPY --from=builder /bin/rollup_relayer /bin/
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["rollup_relayer"]
|
||||
@@ -95,7 +95,8 @@ func (c *Cmd) Write(data []byte) (int, error) {
|
||||
if verbose || c.openLog {
|
||||
fmt.Printf("%s:\n\t%v", c.name, out)
|
||||
} else if strings.Contains(strings.ToLower(out), "error") ||
|
||||
strings.Contains(strings.ToLower(out), "warning") {
|
||||
strings.Contains(strings.ToLower(out), "warning") ||
|
||||
strings.Contains(strings.ToLower(out), "info") {
|
||||
fmt.Printf("%s:\n\t%v", c.name, out)
|
||||
}
|
||||
go c.checkFuncs.IterCb(func(_ string, value interface{}) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
var tag = "v4.3.52"
|
||||
var tag = "v4.3.45"
|
||||
|
||||
var commit = func() string {
|
||||
if info, ok := debug.ReadBuildInfo(); ok {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Scroll Contracts
|
||||
|
||||
This directory contains the solidity code for Scroll L1 bridge and rollup contracts and L2 bridge and pre-deployed contracts. You can also find contract APIs and more details in the [`docs`](./docs) folder.
|
||||
This directory contains the solidity code for Scroll L1 bridge and rollup contracts and L2 bridge and pre-deployed contracts. The [`specs`](../specs/) folder describes the overall Scroll protocol including the cross-domain messaging and rollup process. You can also find contract APIs and more details in the [`docs`](./docs) folder.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
|
||||
@@ -550,50 +550,3 @@ Emitted when token mapping for ERC1155 token is updated.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ function initialize(address _counterpart, address _messenger) external nonpayabl
|
||||
|
||||
Initialize the storage of L1ERC721Gateway.
|
||||
|
||||
*The parameters `_counterpart` and `_messenger` are no longer used.*
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
@@ -489,50 +489,3 @@ Emitted when token mapping for ERC721 token is updated.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ function ethGateway() external view returns (address)
|
||||
|
||||
The address of L1ETHGateway.
|
||||
|
||||
*This variable is no longer used.*
|
||||
|
||||
|
||||
|
||||
#### Returns
|
||||
@@ -286,7 +286,7 @@ function initialize(address _ethGateway, address _defaultERC20Gateway) external
|
||||
|
||||
Initialize the storage of L1GatewayRouter.
|
||||
|
||||
*The parameters `_ethGateway` is no longer used.*
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
@@ -295,23 +295,6 @@ Initialize the storage of L1GatewayRouter.
|
||||
| _ethGateway | address | The address of L1ETHGateway contract. |
|
||||
| _defaultERC20Gateway | address | The address of default ERC20 Gateway contract. |
|
||||
|
||||
### messenger
|
||||
|
||||
```solidity
|
||||
function messenger() external view returns (address)
|
||||
```
|
||||
|
||||
The address of `L1ScrollMessenger`.
|
||||
|
||||
|
||||
|
||||
|
||||
#### Returns
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _0 | address | undefined |
|
||||
|
||||
### owner
|
||||
|
||||
```solidity
|
||||
@@ -635,17 +618,3 @@ Emitted when the address of ETH Gateway is updated.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ function initialize(address _counterpart, address _feeVault, address _rollup, ad
|
||||
|
||||
Initialize the storage of L1ScrollMessenger.
|
||||
|
||||
*The parameters `_counterpart`, `_rollup` and `_messageQueue` are no longer used.*
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
@@ -611,17 +611,3 @@ Emitted when the maximum number of times each message can be replayed is updated
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ function initialize(address _counterpart, address _router, address _messenger, a
|
||||
|
||||
Initialize the storage of L1StandardERC20Gateway.
|
||||
|
||||
*The parameters `_counterpart`, `_router`, `_messenger`, `_l2TokenImplementation` and `_l2TokenFactory` are no longer used.*
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
@@ -374,50 +374,3 @@ Emitted when some ERC20 token is refunded.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -372,50 +372,3 @@ Emitted when some ERC20 token is refunded.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -114,16 +114,16 @@ Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient's
|
||||
function initialize(address _counterpart, address _messenger) external nonpayable
|
||||
```
|
||||
|
||||
Initialize the storage of `L2ERC1155Gateway`.
|
||||
|
||||
*The parameters `_counterpart` and `_messenger` are no longer used.*
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _counterpart | address | The address of `L1ERC1155Gateway` contract in L1. |
|
||||
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
|
||||
| _counterpart | address | undefined |
|
||||
| _messenger | address | undefined |
|
||||
|
||||
### messenger
|
||||
|
||||
@@ -496,50 +496,3 @@ Emitted when the ERC1155 NFT is transfered to gateway on layer 2.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -110,16 +110,16 @@ Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient's
|
||||
function initialize(address _counterpart, address _messenger) external nonpayable
|
||||
```
|
||||
|
||||
Initialize the storage of `L2ERC721Gateway`.
|
||||
|
||||
*The parameters `_counterpart` and `_messenger` are no longer used.*
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _counterpart | address | The address of `L1ERC721Gateway` contract in L1. |
|
||||
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
|
||||
| _counterpart | address | undefined |
|
||||
| _messenger | address | undefined |
|
||||
|
||||
### messenger
|
||||
|
||||
@@ -437,50 +437,3 @@ Emitted when the ERC721 NFT is transfered to gateway on layer 2.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -189,23 +189,6 @@ function initialize(address _ethGateway, address _defaultERC20Gateway) external
|
||||
| _ethGateway | address | undefined |
|
||||
| _defaultERC20Gateway | address | undefined |
|
||||
|
||||
### messenger
|
||||
|
||||
```solidity
|
||||
function messenger() external view returns (address)
|
||||
```
|
||||
|
||||
The address of `L2ScrollMessenger`.
|
||||
|
||||
|
||||
|
||||
|
||||
#### Returns
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _0 | address | undefined |
|
||||
|
||||
### owner
|
||||
|
||||
```solidity
|
||||
@@ -581,17 +564,3 @@ Emitted when someone withdraw ETH from L2 to L1.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ The address of fee vault, collecting cross domain messaging fee.
|
||||
### initialize
|
||||
|
||||
```solidity
|
||||
function initialize(address) external nonpayable
|
||||
function initialize(address _counterpart) external nonpayable
|
||||
```
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ function initialize(address) external nonpayable
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _0 | address | undefined |
|
||||
| _counterpart | address | undefined |
|
||||
|
||||
### isL1MessageExecuted
|
||||
|
||||
@@ -448,17 +448,3 @@ Emitted when the maximum number of times each message can fail in L2 is updated.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -98,18 +98,18 @@ Return the corresponding l2 token address given l1 token address.
|
||||
function initialize(address _counterpart, address _router, address _messenger, address _tokenFactory) external nonpayable
|
||||
```
|
||||
|
||||
Initialize the storage of L2StandardERC20Gateway.
|
||||
|
||||
*The parameters `_counterpart`, `_router`, `_messenger` and `_tokenFactory` are no longer used.*
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _counterpart | address | The address of L1ETHGateway in L1. |
|
||||
| _router | address | The address of L2GatewayRouter. |
|
||||
| _messenger | address | The address of L2ScrollMessenger. |
|
||||
| _tokenFactory | address | The address of ScrollStandardERC20Factory. |
|
||||
| _counterpart | address | undefined |
|
||||
| _router | address | undefined |
|
||||
| _messenger | address | undefined |
|
||||
| _tokenFactory | address | undefined |
|
||||
|
||||
### messenger
|
||||
|
||||
@@ -344,50 +344,3 @@ Emitted when someone withdraw ERC20 token from L2 to L1.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -115,17 +115,17 @@ Return the corresponding l2 token address given l1 token address.
|
||||
function initialize(address _counterpart, address _router, address _messenger) external nonpayable
|
||||
```
|
||||
|
||||
Initialize the storage of `L2WETHGateway`.
|
||||
|
||||
*The parameters `_counterpart`, `_router` and `_messenger` are no longer used.*
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _counterpart | address | The address of `L1WETHGateway` contract in L1. |
|
||||
| _router | address | The address of `L2GatewayRouter` contract in L2. |
|
||||
| _messenger | address | The address of `L2ScrollMessenger` contract in L2. |
|
||||
| _counterpart | address | undefined |
|
||||
| _router | address | undefined |
|
||||
| _messenger | address | undefined |
|
||||
|
||||
### l1WETH
|
||||
|
||||
@@ -360,50 +360,3 @@ Emitted when someone withdraw ERC20 token from L2 to L1.
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorCallerIsNotCounterpartGateway
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotCounterpartGateway()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the cross chain sender is not the counterpart gateway contract.*
|
||||
|
||||
|
||||
### ErrorCallerIsNotMessenger
|
||||
|
||||
```solidity
|
||||
error ErrorCallerIsNotMessenger()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the caller is not corresponding `L1ScrollMessenger` or `L2ScrollMessenger`.*
|
||||
|
||||
|
||||
### ErrorNotInDropMessageContext
|
||||
|
||||
```solidity
|
||||
error ErrorNotInDropMessageContext()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when ScrollMessenger is not dropping message.*
|
||||
|
||||
|
||||
### ErrorZeroAddress
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -148,17 +148,17 @@ Import layer 2 genesis block
|
||||
function initialize(address _messageQueue, address _verifier, uint256 _maxNumTxInChunk) external nonpayable
|
||||
```
|
||||
|
||||
Initialize the storage of ScrollChain.
|
||||
|
||||
*The parameters `_messageQueue` are no longer used.*
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _messageQueue | address | The address of `L1MessageQueue` contract. |
|
||||
| _verifier | address | The address of zkevm verifier contract. |
|
||||
| _maxNumTxInChunk | uint256 | The maximum number of transactions allowed in each chunk. |
|
||||
| _messageQueue | address | undefined |
|
||||
| _verifier | address | undefined |
|
||||
| _maxNumTxInChunk | uint256 | undefined |
|
||||
|
||||
### isBatchFinalized
|
||||
|
||||
@@ -283,7 +283,7 @@ The maximum number of transactions allowed in each chunk.
|
||||
function messageQueue() external view returns (address)
|
||||
```
|
||||
|
||||
The address of L1MessageQueue contract.
|
||||
The address of L1MessageQueue.
|
||||
|
||||
|
||||
|
||||
@@ -436,6 +436,22 @@ Update the value of `maxNumTxInChunk`.
|
||||
|---|---|---|
|
||||
| _maxNumTxInChunk | uint256 | The new value of `maxNumTxInChunk`. |
|
||||
|
||||
### updateVerifier
|
||||
|
||||
```solidity
|
||||
function updateVerifier(address _newVerifier) external nonpayable
|
||||
```
|
||||
|
||||
Update the address verifier contract.
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| _newVerifier | address | The address of new verifier contract. |
|
||||
|
||||
### verifier
|
||||
|
||||
```solidity
|
||||
@@ -648,19 +664,22 @@ Emitted when owner updates the status of sequencer.
|
||||
| account `indexed` | address | The address of account updated. |
|
||||
| status | bool | The status of the account updated. |
|
||||
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
### ErrorZeroAddress
|
||||
### UpdateVerifier
|
||||
|
||||
```solidity
|
||||
error ErrorZeroAddress()
|
||||
event UpdateVerifier(address indexed oldVerifier, address indexed newVerifier)
|
||||
```
|
||||
|
||||
|
||||
|
||||
*Thrown when the given address is `address(0)`.*
|
||||
Emitted when the address of rollup verifier is updated.
|
||||
|
||||
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|---|---|---|
|
||||
| oldVerifier `indexed` | address | The address of old rollup verifier. |
|
||||
| newVerifier `indexed` | address | The address of new rollup verifier. |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ describe("EnforcedTxGateway.spec", async () => {
|
||||
let oracle: L2GasPriceOracle;
|
||||
let queue: L1MessageQueue;
|
||||
|
||||
const deployProxy = async (name: string, admin: string, args: any[]): Promise<string> => {
|
||||
const deployProxy = async (name: string, admin: string): Promise<string> => {
|
||||
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
|
||||
const Factory = await ethers.getContractFactory(name, deployer);
|
||||
const impl = args.length > 0 ? await Factory.deploy(...args) : await Factory.deploy();
|
||||
const impl = await Factory.deploy();
|
||||
await impl.deployed();
|
||||
const proxy = await TransparentUpgradeableProxy.deploy(impl.address, admin, "0x");
|
||||
await proxy.deployed();
|
||||
@@ -34,21 +34,17 @@ describe("EnforcedTxGateway.spec", async () => {
|
||||
const admin = await ProxyAdmin.deploy();
|
||||
await admin.deployed();
|
||||
|
||||
gateway = await ethers.getContractAt(
|
||||
"EnforcedTxGateway",
|
||||
await deployProxy("EnforcedTxGateway", admin.address, []),
|
||||
deployer
|
||||
);
|
||||
|
||||
queue = await ethers.getContractAt(
|
||||
"L1MessageQueue",
|
||||
await deployProxy("L1MessageQueue", admin.address, [deployer.address, deployer.address, gateway.address]),
|
||||
deployer
|
||||
);
|
||||
queue = await ethers.getContractAt("L1MessageQueue", await deployProxy("L1MessageQueue", admin.address), deployer);
|
||||
|
||||
oracle = await ethers.getContractAt(
|
||||
"L2GasPriceOracle",
|
||||
await deployProxy("L2GasPriceOracle", admin.address, []),
|
||||
await deployProxy("L2GasPriceOracle", admin.address),
|
||||
deployer
|
||||
);
|
||||
|
||||
gateway = await ethers.getContractAt(
|
||||
"EnforcedTxGateway",
|
||||
await deployProxy("EnforcedTxGateway", admin.address),
|
||||
deployer
|
||||
);
|
||||
|
||||
@@ -56,13 +52,7 @@ describe("EnforcedTxGateway.spec", async () => {
|
||||
caller = await MockCaller.deploy();
|
||||
await caller.deployed();
|
||||
|
||||
await queue.initialize(
|
||||
constants.AddressZero,
|
||||
constants.AddressZero,
|
||||
constants.AddressZero,
|
||||
oracle.address,
|
||||
10000000
|
||||
);
|
||||
await queue.initialize(constants.AddressZero, constants.AddressZero, gateway.address, oracle.address, 10000000);
|
||||
await gateway.initialize(queue.address, feeVault.address);
|
||||
await oracle.initialize(21000, 51000, 8, 16);
|
||||
|
||||
|
||||
@@ -1,588 +0,0 @@
|
||||
/* eslint-disable node/no-missing-import */
|
||||
/* eslint-disable node/no-unpublished-import */
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
|
||||
import { expect } from "chai";
|
||||
import { BigNumber, BigNumberish, ContractTransaction, constants } from "ethers";
|
||||
import { keccak256 } from "ethers/lib/utils";
|
||||
import { ethers, network } from "hardhat";
|
||||
|
||||
import {
|
||||
ProxyAdmin,
|
||||
L1GatewayRouter,
|
||||
L2ScrollMessenger,
|
||||
L1ScrollMessenger,
|
||||
L1MessageQueueWithGasPriceOracle,
|
||||
L2GatewayRouter,
|
||||
} from "../typechain";
|
||||
|
||||
describe("GasOptimizationUpgrade.spec", async () => {
|
||||
const L1_ROUTER = "0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6";
|
||||
const L2_ROUTER = "0x4C0926FF5252A435FD19e10ED15e5a249Ba19d79";
|
||||
const L1_MESSENGER = "0x6774Bcbd5ceCeF1336b5300fb5186a12DDD8b367";
|
||||
const L2_MESSENGER = "0x781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC";
|
||||
const L1_MESSAGE_QUEUE = "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B";
|
||||
const L2_MESSAGE_QUEUE = "0x5300000000000000000000000000000000000000";
|
||||
const SCROLL_CHAIN = "0xa13BAF47339d63B743e7Da8741db5456DAc1E556";
|
||||
|
||||
let deployer: SignerWithAddress;
|
||||
|
||||
let proxyAdmin: ProxyAdmin;
|
||||
|
||||
const mockERC20Balance = async (tokenAddress: string, balance: BigNumber, slot: BigNumberish) => {
|
||||
const storageSlot = keccak256(
|
||||
ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [deployer.address, slot])
|
||||
);
|
||||
await ethers.provider.send("hardhat_setStorageAt", [
|
||||
tokenAddress,
|
||||
storageSlot,
|
||||
ethers.utils.hexlify(ethers.utils.zeroPad(balance.toHexString(), 32)),
|
||||
]);
|
||||
const token = await ethers.getContractAt("MockERC20", tokenAddress, deployer);
|
||||
expect(await token.balanceOf(deployer.address)).to.eq(balance);
|
||||
};
|
||||
|
||||
const mockETHBalance = async (balance: BigNumber) => {
|
||||
await network.provider.send("hardhat_setBalance", [deployer.address, balance.toHexString()]);
|
||||
expect(await deployer.getBalance()).to.eq(balance);
|
||||
};
|
||||
|
||||
const showGasUsage = async (tx: ContractTransaction, desc: string) => {
|
||||
const receipt = await tx.wait();
|
||||
console.log(`${desc}: GasUsed[${receipt.gasUsed}]`);
|
||||
};
|
||||
|
||||
context("L1 upgrade", async () => {
|
||||
let forkBlock: number;
|
||||
let router: L1GatewayRouter;
|
||||
let messenger: L1ScrollMessenger;
|
||||
let queue: L1MessageQueueWithGasPriceOracle;
|
||||
|
||||
beforeEach(async () => {
|
||||
// fork network
|
||||
const provider = new ethers.providers.JsonRpcProvider("https://rpc.ankr.com/eth");
|
||||
if (!forkBlock) {
|
||||
forkBlock = (await provider.getBlockNumber()) - 10;
|
||||
}
|
||||
await network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
jsonRpcUrl: "https://rpc.ankr.com/eth",
|
||||
blockNumber: forkBlock,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
await network.provider.request({
|
||||
method: "hardhat_impersonateAccount",
|
||||
params: ["0x1100000000000000000000000000000000000011"],
|
||||
});
|
||||
|
||||
// mock eth balance
|
||||
deployer = await ethers.getSigner("0x1100000000000000000000000000000000000011");
|
||||
await mockETHBalance(ethers.utils.parseEther("1000"));
|
||||
|
||||
// mock owner of proxy admin
|
||||
proxyAdmin = await ethers.getContractAt("ProxyAdmin", "0xEB803eb3F501998126bf37bB823646Ed3D59d072", deployer);
|
||||
await ethers.provider.send("hardhat_setStorageAt", [
|
||||
proxyAdmin.address,
|
||||
"0x0",
|
||||
ethers.utils.hexlify(ethers.utils.zeroPad(deployer.address, 32)),
|
||||
]);
|
||||
expect(await proxyAdmin.owner()).to.eq(deployer.address);
|
||||
|
||||
router = await ethers.getContractAt("L1GatewayRouter", L1_ROUTER, deployer);
|
||||
messenger = await ethers.getContractAt("L1ScrollMessenger", L1_MESSENGER, deployer);
|
||||
queue = await ethers.getContractAt("L1MessageQueueWithGasPriceOracle", L1_MESSAGE_QUEUE, deployer);
|
||||
});
|
||||
|
||||
const upgradeL1 = async (proxy: string, impl: string) => {
|
||||
await proxyAdmin.upgrade(proxy, impl);
|
||||
const L1ScrollMessenger = await ethers.getContractFactory("L1ScrollMessenger", deployer);
|
||||
const L1MessageQueueWithGasPriceOracle = await ethers.getContractFactory(
|
||||
"L1MessageQueueWithGasPriceOracle",
|
||||
deployer
|
||||
);
|
||||
const ScrollChain = await ethers.getContractFactory("ScrollChain", deployer);
|
||||
await proxyAdmin.upgrade(
|
||||
L1_MESSENGER,
|
||||
(
|
||||
await L1ScrollMessenger.deploy(L2_MESSENGER, SCROLL_CHAIN, L1_MESSAGE_QUEUE)
|
||||
).address
|
||||
);
|
||||
await proxyAdmin.upgrade(
|
||||
L1_MESSAGE_QUEUE,
|
||||
(
|
||||
await L1MessageQueueWithGasPriceOracle.deploy(
|
||||
L1_MESSENGER,
|
||||
SCROLL_CHAIN,
|
||||
"0x72CAcBcfDe2d1e19122F8A36a4d6676cd39d7A5d"
|
||||
)
|
||||
).address
|
||||
);
|
||||
await queue.initializeV2();
|
||||
await proxyAdmin.upgrade(
|
||||
SCROLL_CHAIN,
|
||||
(
|
||||
await ScrollChain.deploy(534352, L1_MESSAGE_QUEUE, "0xA2Ab526e5C5491F10FC05A55F064BF9F7CEf32a0")
|
||||
).address
|
||||
);
|
||||
};
|
||||
|
||||
it.skip("should succeed on L1ETHGateway", async () => {
|
||||
const L1_GATEWAY = "0x7F2b8C31F88B6006c382775eea88297Ec1e3E905";
|
||||
const L2_GATEWAY = "0x6EA73e05AdC79974B931123675ea8F78FfdacDF0";
|
||||
const L1ETHGateway = await ethers.getContractFactory("L1ETHGateway", deployer);
|
||||
const impl = await L1ETHGateway.deploy(L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L1ETHGateway", L1_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseEther("1");
|
||||
const fee = await queue.estimateCrossDomainMessageFee(1e6);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn.add(fee) }),
|
||||
"L1ETHGateway.depositETH before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn.add(fee) }),
|
||||
"L1GatewayRouter.depositETH before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
|
||||
value: amountIn.add(fee),
|
||||
}),
|
||||
"L1ScrollMessenger.sendMessage before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL1(L1_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn.add(fee) }),
|
||||
"L1ETHGateway.depositETH after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn.add(fee) }),
|
||||
"L1GatewayRouter.depositETH after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
|
||||
value: amountIn.add(fee),
|
||||
}),
|
||||
"L1ScrollMessenger.sendMessage after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L1WETHGateway", async () => {
|
||||
const L1_WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
|
||||
const L2_WETH = "0x5300000000000000000000000000000000000004";
|
||||
const L1_GATEWAY = "0x7AC440cAe8EB6328de4fA621163a792c1EA9D4fE";
|
||||
const L2_GATEWAY = "0x7003E7B7186f0E6601203b99F7B8DECBfA391cf9";
|
||||
const L1WETHGateway = await ethers.getContractFactory("L1WETHGateway", deployer);
|
||||
const impl = await L1WETHGateway.deploy(L1_WETH, L2_WETH, L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L1WETHGateway", L1_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseEther("1");
|
||||
const fee = await queue.estimateCrossDomainMessageFee(1e6);
|
||||
const token = await ethers.getContractAt("MockERC20", L1_WETH, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 3);
|
||||
await token.approve(L1_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L1_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
|
||||
"L1WETHGateway.depositERC20 WETH before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 WETH before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL1(L1_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
|
||||
"L1WETHGateway.depositERC20 WETH after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_WETH, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 WETH after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L1StandardERC20Gateway", async () => {
|
||||
const L1_USDT = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
|
||||
const L1_GATEWAY = "0xD8A791fE2bE73eb6E6cF1eb0cb3F36adC9B3F8f9";
|
||||
const L2_GATEWAY = "0xE2b4795039517653c5Ae8C2A9BFdd783b48f447A";
|
||||
const L1StandardERC20Gateway = await ethers.getContractFactory("L1StandardERC20Gateway", deployer);
|
||||
const impl = await L1StandardERC20Gateway.deploy(
|
||||
L2_GATEWAY,
|
||||
L1_ROUTER,
|
||||
L1_MESSENGER,
|
||||
"0xC7d86908ccf644Db7C69437D5852CedBC1aD3f69",
|
||||
"0x66e5312EDeEAef6e80759A0F789e7914Fb401484"
|
||||
);
|
||||
const gateway = await ethers.getContractAt("L1StandardERC20Gateway", L1_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseUnits("1", 6);
|
||||
const fee = await queue.estimateCrossDomainMessageFee(1e6);
|
||||
const token = await ethers.getContractAt("MockERC20", L1_USDT, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 2);
|
||||
await token.approve(L1_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L1_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
|
||||
"L1StandardERC20Gateway.depositERC20 USDT before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 USDT before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL1(L1_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
|
||||
"L1StandardERC20Gateway.depositERC20 USDT after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_USDT, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 USDT after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L1CustomERC20Gateway", async () => {
|
||||
const L1_DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
|
||||
const L1_GATEWAY = "0x67260A8B73C5B77B55c1805218A42A7A6F98F515";
|
||||
const L2_GATEWAY = "0xaC78dff3A87b5b534e366A93E785a0ce8fA6Cc62";
|
||||
const L1CustomERC20Gateway = await ethers.getContractFactory("L1CustomERC20Gateway", deployer);
|
||||
const impl = await L1CustomERC20Gateway.deploy(L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L1CustomERC20Gateway", L1_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseUnits("1", 18);
|
||||
const fee = await queue.estimateCrossDomainMessageFee(1e6);
|
||||
const token = await ethers.getContractAt("MockERC20", L1_DAI, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 2);
|
||||
await token.approve(L1_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L1_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
|
||||
"L1CustomERC20Gateway.depositERC20 DAI before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 DAI before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL1(L1_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
|
||||
"L1CustomERC20Gateway.depositERC20 DAI after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_DAI, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 DAI after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L1USDCGateway", async () => {
|
||||
const L1_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
|
||||
const L2_USDC = "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4";
|
||||
const L1_GATEWAY = "0xf1AF3b23DE0A5Ca3CAb7261cb0061C0D779A5c7B";
|
||||
const L2_GATEWAY = "0x33B60d5Dd260d453cAC3782b0bDC01ce84672142";
|
||||
const L1USDCGateway = await ethers.getContractFactory("L1USDCGateway", deployer);
|
||||
const impl = await L1USDCGateway.deploy(L1_USDC, L2_USDC, L2_GATEWAY, L1_ROUTER, L1_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L1USDCGateway", L1_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseUnits("1", 6);
|
||||
const fee = await queue.estimateCrossDomainMessageFee(1e6);
|
||||
const token = await ethers.getContractAt("MockERC20", L1_USDC, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 9);
|
||||
await token.approve(L1_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L1_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
|
||||
"L1USDCGateway.depositERC20 USDC before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 USDC before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL1(L1_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
|
||||
"L1USDCGateway.depositERC20 USDC after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["depositERC20(address,uint256,uint256)"](L1_USDC, amountIn, 1e6, { value: fee }),
|
||||
"L1GatewayRouter.depositERC20 USDC after upgrade"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context("L2 upgrade", async () => {
|
||||
let forkBlock: number;
|
||||
let router: L2GatewayRouter;
|
||||
let messenger: L2ScrollMessenger;
|
||||
|
||||
beforeEach(async () => {
|
||||
// fork network
|
||||
const provider = new ethers.providers.JsonRpcProvider("https://rpc.scroll.io");
|
||||
if (!forkBlock) {
|
||||
forkBlock = (await provider.getBlockNumber()) - 31;
|
||||
}
|
||||
await network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
jsonRpcUrl: "https://rpc.scroll.io",
|
||||
blockNumber: forkBlock,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
await network.provider.request({
|
||||
method: "hardhat_impersonateAccount",
|
||||
params: ["0x1100000000000000000000000000000000000011"],
|
||||
});
|
||||
|
||||
// mock eth balance
|
||||
deployer = await ethers.getSigner("0x1100000000000000000000000000000000000011");
|
||||
await mockETHBalance(ethers.utils.parseEther("1000"));
|
||||
|
||||
// mock owner of proxy admin
|
||||
proxyAdmin = await ethers.getContractAt("ProxyAdmin", "0xA76acF000C890b0DD7AEEf57627d9899F955d026", deployer);
|
||||
await ethers.provider.send("hardhat_setStorageAt", [
|
||||
proxyAdmin.address,
|
||||
"0x0",
|
||||
ethers.utils.hexlify(ethers.utils.zeroPad(deployer.address, 32)),
|
||||
]);
|
||||
expect(await proxyAdmin.owner()).to.eq(deployer.address);
|
||||
|
||||
router = await ethers.getContractAt("L2GatewayRouter", L2_ROUTER, deployer);
|
||||
messenger = await ethers.getContractAt("L2ScrollMessenger", L2_MESSENGER, deployer);
|
||||
});
|
||||
|
||||
const upgradeL2 = async (proxy: string, impl: string) => {
|
||||
await proxyAdmin.upgrade(proxy, impl);
|
||||
const L2ScrollMessenger = await ethers.getContractFactory("L2ScrollMessenger", deployer);
|
||||
await proxyAdmin.upgrade(L2_MESSENGER, (await L2ScrollMessenger.deploy(L1_MESSENGER, L2_MESSAGE_QUEUE)).address);
|
||||
};
|
||||
|
||||
it.skip("should succeed on L2ETHGateway", async () => {
|
||||
const L1_GATEWAY = "0x7F2b8C31F88B6006c382775eea88297Ec1e3E905";
|
||||
const L2_GATEWAY = "0x6EA73e05AdC79974B931123675ea8F78FfdacDF0";
|
||||
const L2ETHGateway = await ethers.getContractFactory("L2ETHGateway", deployer);
|
||||
const impl = await L2ETHGateway.deploy(L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L2ETHGateway", L2_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseEther("1");
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
|
||||
"L2ETHGateway.withdrawETH before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
|
||||
"L2GatewayRouter.withdrawETH before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
|
||||
value: amountIn,
|
||||
}),
|
||||
"L2ScrollMessenger.sendMessage before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL2(L2_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
|
||||
"L2ETHGateway.withdrawETH after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawETH(uint256,uint256)"](amountIn, 1e6, { value: amountIn }),
|
||||
"L2GatewayRouter.withdrawETH after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await messenger["sendMessage(address,uint256,bytes,uint256)"](deployer.address, amountIn, "0x", 1e6, {
|
||||
value: amountIn,
|
||||
}),
|
||||
"L2ScrollMessenger.sendMessage after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L2WETHGateway", async () => {
|
||||
const L1_WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
|
||||
const L2_WETH = "0x5300000000000000000000000000000000000004";
|
||||
const L1_GATEWAY = "0x7AC440cAe8EB6328de4fA621163a792c1EA9D4fE";
|
||||
const L2_GATEWAY = "0x7003E7B7186f0E6601203b99F7B8DECBfA391cf9";
|
||||
const L2WETHGateway = await ethers.getContractFactory("L2WETHGateway", deployer);
|
||||
const impl = await L2WETHGateway.deploy(L2_WETH, L1_WETH, L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L2WETHGateway", L2_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseEther("1");
|
||||
const token = await ethers.getContractAt("MockERC20", L2_WETH, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 0);
|
||||
await token.approve(L2_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L2_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
|
||||
"L2WETHGateway.withdrawERC20 WETH before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 WETH before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL2(L2_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
|
||||
"L2WETHGateway.withdrawERC20 WETH after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_WETH, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 WETH after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L2StandardERC20Gateway", async () => {
|
||||
const L2_USDT = "0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df";
|
||||
const L1_GATEWAY = "0xD8A791fE2bE73eb6E6cF1eb0cb3F36adC9B3F8f9";
|
||||
const L2_GATEWAY = "0xE2b4795039517653c5Ae8C2A9BFdd783b48f447A";
|
||||
const L2StandardERC20Gateway = await ethers.getContractFactory("L2StandardERC20Gateway", deployer);
|
||||
const impl = await L2StandardERC20Gateway.deploy(
|
||||
L1_GATEWAY,
|
||||
L2_ROUTER,
|
||||
L2_MESSENGER,
|
||||
"0x66e5312EDeEAef6e80759A0F789e7914Fb401484"
|
||||
);
|
||||
const gateway = await ethers.getContractAt("L2StandardERC20Gateway", L2_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseUnits("1", 6);
|
||||
const token = await ethers.getContractAt("MockERC20", L2_USDT, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 51);
|
||||
await token.approve(L2_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L2_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
|
||||
"L2StandardERC20Gateway.withdrawERC20 USDT before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 USDT before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL2(L2_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
|
||||
"L2StandardERC20Gateway.withdrawERC20 USDT after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_USDT, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 USDT after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L2CustomERC20Gateway", async () => {
|
||||
const L2_DAI = "0xcA77eB3fEFe3725Dc33bccB54eDEFc3D9f764f97";
|
||||
const L1_GATEWAY = "0x67260A8B73C5B77B55c1805218A42A7A6F98F515";
|
||||
const L2_GATEWAY = "0xaC78dff3A87b5b534e366A93E785a0ce8fA6Cc62";
|
||||
const L2CustomERC20Gateway = await ethers.getContractFactory("L2CustomERC20Gateway", deployer);
|
||||
const impl = await L2CustomERC20Gateway.deploy(L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L2CustomERC20Gateway", L2_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseUnits("1", 18);
|
||||
const token = await ethers.getContractAt("MockERC20", L2_DAI, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 51);
|
||||
await token.approve(L1_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L1_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
|
||||
"L2CustomERC20Gateway.withdrawERC20 DAI before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 DAI before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL2(L2_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
|
||||
"L2CustomERC20Gateway.withdrawERC20 DAI after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_DAI, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 DAI after upgrade"
|
||||
);
|
||||
});
|
||||
|
||||
it.skip("should succeed on L2USDCGateway", async () => {
|
||||
const L1_USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
|
||||
const L2_USDC = "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4";
|
||||
const L1_GATEWAY = "0xf1AF3b23DE0A5Ca3CAb7261cb0061C0D779A5c7B";
|
||||
const L2_GATEWAY = "0x33B60d5Dd260d453cAC3782b0bDC01ce84672142";
|
||||
const L2USDCGateway = await ethers.getContractFactory("L2USDCGateway", deployer);
|
||||
const impl = await L2USDCGateway.deploy(L1_USDC, L2_USDC, L1_GATEWAY, L2_ROUTER, L2_MESSENGER);
|
||||
const gateway = await ethers.getContractAt("L2USDCGateway", L2_GATEWAY, deployer);
|
||||
const amountIn = ethers.utils.parseUnits("1", 6);
|
||||
const token = await ethers.getContractAt("MockERC20", L2_USDC, deployer);
|
||||
await mockERC20Balance(token.address, amountIn.mul(10), 9);
|
||||
await token.approve(L2_GATEWAY, constants.MaxUint256);
|
||||
await token.approve(L2_ROUTER, constants.MaxUint256);
|
||||
|
||||
// before upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
|
||||
"L2USDCGateway.withdrawERC20 USDC before upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 USDC before upgrade"
|
||||
);
|
||||
|
||||
// do upgrade
|
||||
await upgradeL2(L2_GATEWAY, impl.address);
|
||||
|
||||
// after upgrade
|
||||
await showGasUsage(
|
||||
await gateway["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
|
||||
"L2USDCGateway.withdrawERC20 USDC after upgrade"
|
||||
);
|
||||
await showGasUsage(
|
||||
await router["withdrawERC20(address,uint256,uint256)"](L2_USDC, amountIn, 1e6),
|
||||
"L2GatewayRouter.withdrawERC20 USDC after upgrade"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -17,10 +17,10 @@ describe("L1MessageQueue", async () => {
|
||||
let oracle: L2GasPriceOracle;
|
||||
let queue: L1MessageQueue;
|
||||
|
||||
const deployProxy = async (name: string, admin: string, args: any[]): Promise<string> => {
|
||||
const deployProxy = async (name: string, admin: string): Promise<string> => {
|
||||
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
|
||||
const Factory = await ethers.getContractFactory(name, deployer);
|
||||
const impl = args.length > 0 ? await Factory.deploy(...args) : await Factory.deploy();
|
||||
const impl = await Factory.deploy();
|
||||
await impl.deployed();
|
||||
const proxy = await TransparentUpgradeableProxy.deploy(impl.address, admin, "0x");
|
||||
await proxy.deployed();
|
||||
@@ -34,20 +34,16 @@ describe("L1MessageQueue", async () => {
|
||||
const admin = await ProxyAdmin.deploy();
|
||||
await admin.deployed();
|
||||
|
||||
queue = await ethers.getContractAt(
|
||||
"L1MessageQueue",
|
||||
await deployProxy("L1MessageQueue", admin.address, [messenger.address, scrollChain.address, gateway.address]),
|
||||
deployer
|
||||
);
|
||||
queue = await ethers.getContractAt("L1MessageQueue", await deployProxy("L1MessageQueue", admin.address), deployer);
|
||||
|
||||
oracle = await ethers.getContractAt(
|
||||
"L2GasPriceOracle",
|
||||
await deployProxy("L2GasPriceOracle", admin.address, []),
|
||||
await deployProxy("L2GasPriceOracle", admin.address),
|
||||
deployer
|
||||
);
|
||||
|
||||
await oracle.initialize(21000, 50000, 8, 16);
|
||||
await queue.initialize(messenger.address, scrollChain.address, constants.AddressZero, oracle.address, 10000000);
|
||||
await queue.initialize(messenger.address, scrollChain.address, gateway.address, oracle.address, 10000000);
|
||||
});
|
||||
|
||||
context("auth", async () => {
|
||||
@@ -82,6 +78,22 @@ describe("L1MessageQueue", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
context("#updateEnforcedTxGateway", async () => {
|
||||
it("should revert, when non-owner call", async () => {
|
||||
await expect(queue.connect(signer).updateEnforcedTxGateway(constants.AddressZero)).to.revertedWith(
|
||||
"Ownable: caller is not the owner"
|
||||
);
|
||||
});
|
||||
|
||||
it("should succeed", async () => {
|
||||
expect(await queue.enforcedTxGateway()).to.eq(gateway.address);
|
||||
await expect(queue.updateEnforcedTxGateway(deployer.address))
|
||||
.to.emit(queue, "UpdateEnforcedTxGateway")
|
||||
.withArgs(gateway.address, deployer.address);
|
||||
expect(await queue.enforcedTxGateway()).to.eq(deployer.address);
|
||||
});
|
||||
});
|
||||
|
||||
context("#updateMaxGasLimit", async () => {
|
||||
it("should revert, when non-owner call", async () => {
|
||||
await expect(queue.connect(signer).updateMaxGasLimit(0)).to.revertedWith("Ownable: caller is not the owner");
|
||||
|
||||
@@ -12,31 +12,24 @@ describe("ScrollChain", async () => {
|
||||
beforeEach(async () => {
|
||||
const [deployer] = await ethers.getSigners();
|
||||
|
||||
const EmptyContract = await ethers.getContractFactory("EmptyContract", deployer);
|
||||
const empty = await EmptyContract.deploy();
|
||||
await empty.deployed();
|
||||
|
||||
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
|
||||
const admin = await ProxyAdmin.deploy();
|
||||
await admin.deployed();
|
||||
|
||||
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
|
||||
const queueProxy = await TransparentUpgradeableProxy.deploy(empty.address, admin.address, "0x");
|
||||
await queueProxy.deployed();
|
||||
const chainProxy = await TransparentUpgradeableProxy.deploy(empty.address, admin.address, "0x");
|
||||
await chainProxy.deployed();
|
||||
|
||||
const L1MessageQueue = await ethers.getContractFactory("L1MessageQueue", deployer);
|
||||
const queueImpl = await L1MessageQueue.deploy(constants.AddressZero, chainProxy.address, deployer.address);
|
||||
const queueImpl = await L1MessageQueue.deploy();
|
||||
await queueImpl.deployed();
|
||||
await admin.upgrade(queueProxy.address, queueImpl.address);
|
||||
const queueProxy = await TransparentUpgradeableProxy.deploy(queueImpl.address, admin.address, "0x");
|
||||
await queueProxy.deployed();
|
||||
queue = await ethers.getContractAt("L1MessageQueue", queueProxy.address, deployer);
|
||||
|
||||
const ScrollChain = await ethers.getContractFactory("ScrollChain", deployer);
|
||||
const chainImpl = await ScrollChain.deploy(0, queueProxy.address, deployer.address);
|
||||
const chainImpl = await ScrollChain.deploy(0);
|
||||
await chainImpl.deployed();
|
||||
await admin.upgrade(chainProxy.address, chainImpl.address);
|
||||
|
||||
queue = await ethers.getContractAt("L1MessageQueue", queueProxy.address, deployer);
|
||||
const chainProxy = await TransparentUpgradeableProxy.deploy(chainImpl.address, admin.address, "0x");
|
||||
await chainProxy.deployed();
|
||||
chain = await ethers.getContractAt("ScrollChain", chainProxy.address, deployer);
|
||||
|
||||
await chain.initialize(queue.address, constants.AddressZero, 100);
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("ZkEvmVerifierV1", async () => {
|
||||
beforeEach(async () => {
|
||||
[deployer] = await ethers.getSigners();
|
||||
|
||||
const bytecode = hexlify(fs.readFileSync("./src/libraries/verifier/plonk-verifier/plonk_verifier_0.9.8.bin"));
|
||||
const bytecode = hexlify(fs.readFileSync("./src/libraries/verifier/plonk-verifier/plonk_verifier_0.5.1.bin"));
|
||||
const tx = await deployer.sendTransaction({ data: bytecode });
|
||||
const receipt = await tx.wait();
|
||||
|
||||
@@ -25,15 +25,47 @@ describe("ZkEvmVerifierV1", async () => {
|
||||
});
|
||||
|
||||
it("should succeed", async () => {
|
||||
const proof = hexlify(fs.readFileSync("./integration-test/testdata/plonk_verifier_0.9.8_proof.data"));
|
||||
const instances = fs.readFileSync("./integration-test/testdata/plonk_verifier_0.9.8_pi.data");
|
||||
const proof = hexlify(fs.readFileSync("./integration-test/testdata/plonk_verifier_0.5.1_proof.data"));
|
||||
const instances = fs.readFileSync("./integration-test/testdata/plonk_verifier_0.5.1_pi.data");
|
||||
|
||||
const publicInputHash = new Uint8Array(32);
|
||||
for (let i = 0; i < 32; i++) {
|
||||
publicInputHash[i] = instances[i * 32 + 31];
|
||||
}
|
||||
|
||||
expect(hexlify(publicInputHash)).to.eq("0x31b430667bc9e8a8b7eda5e5c76f2250c64023f5f8e0689ac9f4e53f5362da66");
|
||||
// chunk1: https://github.com/scroll-tech/test-traces/blob/674ad743beab04b57da369fa5958fb6824155bfe/erc20/1_transfer.json
|
||||
// 0000000000000005 blockNumber
|
||||
// 0000000064c3ca7c timestamp
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000 baseFee
|
||||
// 00000000007a1200 gasLimit
|
||||
// 0001 numTransactions
|
||||
// 8da3fedb103b6da8ccc2514094336d1a76df166238f4d8e8558fbe54cce2516a tx hash 0
|
||||
// chunk2: https://github.com/scroll-tech/test-traces/blob/674ad743beab04b57da369fa5958fb6824155bfe/erc20/10_transfer.json
|
||||
// 0000000000000006 blockNumber
|
||||
// 0000000064c3ca7f timestamp
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000 baseFee
|
||||
// 00000000007a1200 gasLimit
|
||||
// 000a numTransactions
|
||||
// 419164c1a7213e4e52f8578463c47a01549f69a7ff220d93221ce02909f5b919 tx hash 0
|
||||
// 6c1b03d1a9b5156e189ad2e7ba73ba71d9a83b24f9830f38dd7a597fe1e67167 tx hash 1
|
||||
// 94f981938d02b2c1d91ff370b3ed759dadc617c7347cd4b8552b275edbffd767 tx hash 2
|
||||
// bfe98147fc808a916bdff90e838e77609fd59634787443f6fc58f9a371790d09 tx hash 3
|
||||
// beb9dd0259e7c4f0a8d5ac3ba6aa3940c3e53947395f64e8ee88c7067c6d210e tx hash 4
|
||||
// 208c6c767356552ad8085fa77a99d9154e0c8cf8777e329cb76bcbc969d21fca tx hash 5
|
||||
// 37c8969833fbc6cbb88a63ccef324d7b42d0607ac0094f14e1f6d4e50f84d87f tx hash 6
|
||||
// 088c5ad45a990694ac783207fe6bda9bf97da40e1f3eb468c73941d51b99932c tx hash 7
|
||||
// c3d8ddbdfc67877a253255b9357aabfd062ce80d39eba67547f964c288660065 tx hash 8
|
||||
// ff26ca52c02b97b1a6677263d5d6dec0321fb7b49be44ae0a66ba5482b1180b4 tx hash 9
|
||||
// => chunk 0 data hash: 9390886a7d22aa43aae87e62a350c904fabc5db4487d9b25bdca446ba7ed15a1
|
||||
// => chunk 1 data hash: a8846bf9bc53f30a391ae452b5fd456cb86a99ab7bd2e1e47898ffbe3509e8eb
|
||||
// => batch data hash: ee64d77c2f2e0b2c4ac952a0f54fdba4a217c42eb26a07b28de9fbc7b009acae
|
||||
// 000000000000cf55 layer2ChainId
|
||||
// 02040e949809e8d2e56d35b4dfb876e08ee7b4608d22f23f52052425857c31ba prevStateRoot
|
||||
// 1532cdb7732da0a4ca3044914c6959b7e2b7ba4e913a9f5f0b55051e467412d9 postStateRoot
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000 withdrawRoot
|
||||
// ee64d77c2f2e0b2c4ac952a0f54fdba4a217c42eb26a07b28de9fbc7b009acae batchDataHash
|
||||
// public input hash: 9ea439164727042e029464a40901e52800095c1ade301b63b4b7453880f5723e
|
||||
expect(hexlify(publicInputHash)).to.eq("0x9ea439164727042e029464a40901e52800095c1ade301b63b4b7453880f5723e");
|
||||
|
||||
// verify ok
|
||||
await zkEvmVerifier.verify(proof, publicInputHash);
|
||||
|
||||
BIN
contracts/integration-test/testdata/plonk_verifier_0.5.1_pi.data
vendored
Normal file
BIN
contracts/integration-test/testdata/plonk_verifier_0.5.1_pi.data
vendored
Normal file
Binary file not shown.
BIN
contracts/integration-test/testdata/plonk_verifier_0.5.1_proof.data
vendored
Normal file
BIN
contracts/integration-test/testdata/plonk_verifier_0.5.1_proof.data
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,16 +1,11 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
// solhint-disable no-console
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
|
||||
import {Fallback} from "../../src/misc/Fallback.sol";
|
||||
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract DeployFallbackContracts is Script {
|
||||
uint256 DEPLOYER_PRIVATE_KEY = vm.envUint("DEPLOYER_PRIVATE_KEY");
|
||||
uint256 NUM_CONTRACTS = vm.envUint("NUM_CONTRACTS");
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
// solhint-disable no-console
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
@@ -15,7 +13,7 @@ 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 {L1MessageQueueWithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueWithGasPriceOracle.sol";
|
||||
import {L1MessageQueue} from "../../src/L1/rollup/L1MessageQueue.sol";
|
||||
import {L1ScrollMessenger} from "../../src/L1/L1ScrollMessenger.sol";
|
||||
import {L1StandardERC20Gateway} from "../../src/L1/gateways/L1StandardERC20Gateway.sol";
|
||||
import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol";
|
||||
@@ -25,10 +23,6 @@ import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
|
||||
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
|
||||
import {ZkEvmVerifierV1} from "../../src/libraries/verifier/ZkEvmVerifierV1.sol";
|
||||
|
||||
// solhint-disable max-states-count
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract DeployL1BridgeContracts is Script {
|
||||
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
|
||||
|
||||
@@ -39,45 +33,25 @@ contract DeployL1BridgeContracts is Script {
|
||||
|
||||
address L1_PLONK_VERIFIER_ADDR = vm.envAddress("L1_PLONK_VERIFIER_ADDR");
|
||||
|
||||
address L1_PROXY_ADMIN_ADDR = vm.envAddress("L1_PROXY_ADMIN_ADDR");
|
||||
|
||||
address L1_SCROLL_CHAIN_PROXY_ADDR = vm.envAddress("L1_SCROLL_CHAIN_PROXY_ADDR");
|
||||
address L1_MESSAGE_QUEUE_PROXY_ADDR = vm.envAddress("L1_MESSAGE_QUEUE_PROXY_ADDR");
|
||||
address L1_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L1_SCROLL_MESSENGER_PROXY_ADDR");
|
||||
|
||||
address L2_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_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");
|
||||
|
||||
ZkEvmVerifierV1 zkEvmVerifierV1;
|
||||
MultipleVersionRollupVerifier rollupVerifier;
|
||||
EnforcedTxGateway enforcedTxGateway;
|
||||
ProxyAdmin proxyAdmin;
|
||||
L1GatewayRouter router;
|
||||
|
||||
function run() external {
|
||||
proxyAdmin = ProxyAdmin(L1_PROXY_ADMIN_ADDR);
|
||||
|
||||
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
|
||||
|
||||
deployZkEvmVerifierV1();
|
||||
deployMultipleVersionRollupVerifier();
|
||||
deployProxyAdmin();
|
||||
deployL1Whitelist();
|
||||
deployEnforcedTxGateway();
|
||||
deployL1MessageQueue();
|
||||
deployL2GasPriceOracle();
|
||||
deployScrollChain();
|
||||
deployL1ScrollMessenger();
|
||||
deployL1GatewayRouter();
|
||||
deployL1ETHGateway();
|
||||
deployL1WETHGateway();
|
||||
deployL1StandardERC20Gateway();
|
||||
deployL1GatewayRouter();
|
||||
deployL1ScrollMessenger();
|
||||
deployEnforcedTxGateway();
|
||||
deployL1CustomERC20Gateway();
|
||||
deployL1ERC721Gateway();
|
||||
deployL1ERC1155Gateway();
|
||||
@@ -92,11 +66,17 @@ contract DeployL1BridgeContracts is Script {
|
||||
}
|
||||
|
||||
function deployMultipleVersionRollupVerifier() internal {
|
||||
rollupVerifier = new MultipleVersionRollupVerifier(address(zkEvmVerifierV1));
|
||||
MultipleVersionRollupVerifier rollupVerifier = new MultipleVersionRollupVerifier(address(zkEvmVerifierV1));
|
||||
|
||||
logAddress("L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR", address(rollupVerifier));
|
||||
}
|
||||
|
||||
function deployProxyAdmin() internal {
|
||||
proxyAdmin = new ProxyAdmin();
|
||||
|
||||
logAddress("L1_PROXY_ADMIN_ADDR", address(proxyAdmin));
|
||||
}
|
||||
|
||||
function deployL1Whitelist() internal {
|
||||
address owner = vm.addr(L1_DEPLOYER_PRIVATE_KEY);
|
||||
Whitelist whitelist = new Whitelist(owner);
|
||||
@@ -105,28 +85,26 @@ contract DeployL1BridgeContracts is Script {
|
||||
}
|
||||
|
||||
function deployScrollChain() internal {
|
||||
ScrollChain impl = new ScrollChain(CHAIN_ID_L2, L1_MESSAGE_QUEUE_PROXY_ADDR, address(rollupVerifier));
|
||||
ScrollChain impl = new ScrollChain(CHAIN_ID_L2);
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L1_SCROLL_CHAIN_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1MessageQueue() internal {
|
||||
L1MessageQueueWithGasPriceOracle impl = new L1MessageQueueWithGasPriceOracle(
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L1_SCROLL_CHAIN_PROXY_ADDR,
|
||||
address(enforcedTxGateway)
|
||||
L1MessageQueue impl = new L1MessageQueue();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
logAddress("L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL1ScrollMessenger() internal {
|
||||
L1ScrollMessenger impl = new L1ScrollMessenger(
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L1_SCROLL_CHAIN_PROXY_ADDR,
|
||||
L1_MESSAGE_QUEUE_PROXY_ADDR
|
||||
);
|
||||
|
||||
logAddress("L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L1_MESSAGE_QUEUE_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2GasPriceOracle() internal {
|
||||
@@ -140,8 +118,44 @@ contract DeployL1BridgeContracts is Script {
|
||||
logAddress("L2_GAS_PRICE_ORACLE_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1StandardERC20Gateway() internal {
|
||||
L1StandardERC20Gateway impl = new L1StandardERC20Gateway();
|
||||
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));
|
||||
}
|
||||
|
||||
function deployL1ETHGateway() internal {
|
||||
L1ETHGateway impl = new L1ETHGateway();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
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(L1_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
L1GatewayRouter impl = new L1GatewayRouter();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
@@ -150,64 +164,18 @@ contract DeployL1BridgeContracts is Script {
|
||||
|
||||
logAddress("L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L1_GATEWAY_ROUTER_PROXY_ADDR", address(proxy));
|
||||
|
||||
router = L1GatewayRouter(address(proxy));
|
||||
}
|
||||
|
||||
function deployL1StandardERC20Gateway() internal {
|
||||
L1StandardERC20Gateway impl = new L1StandardERC20Gateway(
|
||||
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L2_SCROLL_STANDARD_ERC20_ADDR,
|
||||
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR
|
||||
function deployL1ScrollMessenger() internal {
|
||||
L1ScrollMessenger impl = new L1ScrollMessenger();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL1ETHGateway() internal {
|
||||
L1ETHGateway impl = new L1ETHGateway(
|
||||
L2_ETH_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
logAddress("L1_ETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL1WETHGateway() internal {
|
||||
L1WETHGateway impl = new L1WETHGateway(
|
||||
L1_WETH_ADDR,
|
||||
L2_WETH_ADDR,
|
||||
L2_WETH_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
logAddress("L1_WETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL1CustomERC20Gateway() internal {
|
||||
L1CustomERC20Gateway impl = new L1CustomERC20Gateway(
|
||||
L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
logAddress("L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL1ERC721Gateway() internal {
|
||||
L1ERC721Gateway impl = new L1ERC721Gateway(L2_ERC721_GATEWAY_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
|
||||
logAddress("L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL1ERC1155Gateway() internal {
|
||||
L1ERC1155Gateway impl = new L1ERC1155Gateway(L2_ERC1155_GATEWAY_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
|
||||
logAddress("L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L1_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployEnforcedTxGateway() internal {
|
||||
@@ -220,7 +188,42 @@ contract DeployL1BridgeContracts is Script {
|
||||
|
||||
logAddress("L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L1_ENFORCED_TX_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
enforcedTxGateway = EnforcedTxGateway(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 {
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
// solhint-disable no-console
|
||||
|
||||
import {Script} from "forge-std/Script.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";
|
||||
|
||||
import {EmptyContract} from "../../src/misc/EmptyContract.sol";
|
||||
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract DeployL1BridgeProxyPlaceholder is Script {
|
||||
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
|
||||
|
||||
ProxyAdmin proxyAdmin;
|
||||
EmptyContract placeholder;
|
||||
|
||||
function run() external {
|
||||
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
|
||||
|
||||
deployProxyAdmin();
|
||||
deployPlaceHolder();
|
||||
deployL1MessageQueue();
|
||||
deployScrollChain();
|
||||
deployL1ETHGateway();
|
||||
deployL1WETHGateway();
|
||||
deployL1StandardERC20Gateway();
|
||||
deployL1ScrollMessenger();
|
||||
deployL1CustomERC20Gateway();
|
||||
deployL1ERC721Gateway();
|
||||
deployL1ERC1155Gateway();
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
function deployProxyAdmin() internal {
|
||||
proxyAdmin = new ProxyAdmin();
|
||||
|
||||
logAddress("L1_PROXY_ADMIN_ADDR", address(proxyAdmin));
|
||||
}
|
||||
|
||||
function deployPlaceHolder() internal {
|
||||
placeholder = new EmptyContract();
|
||||
|
||||
logAddress("L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR", address(placeholder));
|
||||
}
|
||||
|
||||
function deployScrollChain() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_SCROLL_CHAIN_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1MessageQueue() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
logAddress("L1_MESSAGE_QUEUE_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1StandardERC20Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1ETHGateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_ETH_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1WETHGateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_WETH_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1ScrollMessenger() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1CustomERC20Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1ERC721Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L1_ERC721_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL1ERC1155Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
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)))));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
// solhint-disable no-console
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
@@ -24,10 +22,6 @@ import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
|
||||
import {ScrollStandardERC20} from "../../src/libraries/token/ScrollStandardERC20.sol";
|
||||
import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
|
||||
|
||||
// solhint-disable max-states-count
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract DeployL2BridgeContracts is Script {
|
||||
uint256 L2_DEPLOYER_PRIVATE_KEY = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
|
||||
|
||||
@@ -38,18 +32,6 @@ contract DeployL2BridgeContracts is Script {
|
||||
L1GasPriceOracle oracle;
|
||||
L2MessageQueue queue;
|
||||
ProxyAdmin proxyAdmin;
|
||||
L2GatewayRouter router;
|
||||
ScrollStandardERC20Factory factory;
|
||||
|
||||
address L2_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_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_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");
|
||||
|
||||
// predeploy contracts
|
||||
address L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR = vm.envOr("L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR", address(0));
|
||||
@@ -69,11 +51,11 @@ contract DeployL2BridgeContracts is Script {
|
||||
// upgradable
|
||||
deployProxyAdmin();
|
||||
deployL2ScrollMessenger();
|
||||
deployL2GatewayRouter();
|
||||
deployScrollStandardERC20Factory();
|
||||
deployL2StandardERC20Gateway();
|
||||
deployL2ETHGateway();
|
||||
deployL2WETHGateway();
|
||||
deployL2StandardERC20Gateway();
|
||||
deployL2GatewayRouter();
|
||||
deployScrollStandardERC20Factory();
|
||||
deployL2CustomERC20Gateway();
|
||||
deployL2ERC721Gateway();
|
||||
deployL2ERC1155Gateway();
|
||||
@@ -138,13 +120,55 @@ contract DeployL2BridgeContracts is Script {
|
||||
}
|
||||
|
||||
function deployL2ScrollMessenger() internal {
|
||||
L2ScrollMessenger impl = new L2ScrollMessenger(L1_SCROLL_MESSENGER_PROXY_ADDR, address(queue));
|
||||
L2ScrollMessenger impl = new L2ScrollMessenger(address(queue));
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L2_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2StandardERC20Gateway() internal {
|
||||
L2StandardERC20Gateway impl = new L2StandardERC20Gateway();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
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(L2_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
L2GatewayRouter impl = new L2GatewayRouter();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(impl),
|
||||
address(proxyAdmin),
|
||||
@@ -153,70 +177,50 @@ contract DeployL2BridgeContracts is Script {
|
||||
|
||||
logAddress("L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L2_GATEWAY_ROUTER_PROXY_ADDR", address(proxy));
|
||||
|
||||
router = L2GatewayRouter(address(proxy));
|
||||
}
|
||||
|
||||
function deployScrollStandardERC20Factory() internal {
|
||||
ScrollStandardERC20 tokenImpl = new ScrollStandardERC20();
|
||||
factory = new ScrollStandardERC20Factory(address(tokenImpl));
|
||||
ScrollStandardERC20Factory scrollStandardERC20Factory = new ScrollStandardERC20Factory(address(tokenImpl));
|
||||
|
||||
logAddress("L2_SCROLL_STANDARD_ERC20_ADDR", address(tokenImpl));
|
||||
logAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR", address(factory));
|
||||
}
|
||||
|
||||
function deployL2StandardERC20Gateway() internal {
|
||||
L2StandardERC20Gateway impl = new L2StandardERC20Gateway(
|
||||
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
address(factory)
|
||||
);
|
||||
|
||||
logAddress("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL2ETHGateway() internal {
|
||||
L2ETHGateway impl = new L2ETHGateway(
|
||||
L1_ETH_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
logAddress("L2_ETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
}
|
||||
|
||||
function deployL2WETHGateway() internal {
|
||||
L2WETHGateway impl = new L2WETHGateway(
|
||||
L2_WETH_ADDR,
|
||||
L1_WETH_ADDR,
|
||||
L1_WETH_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
logAddress("L2_WETH_GATEWAY_IMPLEMENTATION_ADDR", address(impl));
|
||||
logAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR", address(scrollStandardERC20Factory));
|
||||
}
|
||||
|
||||
function deployL2CustomERC20Gateway() internal {
|
||||
L2CustomERC20Gateway impl = new L2CustomERC20Gateway(
|
||||
L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR,
|
||||
address(router),
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
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(L1_ERC721_GATEWAY_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
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(L1_ERC1155_GATEWAY_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
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 {
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
// solhint-disable no-console
|
||||
|
||||
import {Script} from "forge-std/Script.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";
|
||||
|
||||
import {EmptyContract} from "../../src/misc/EmptyContract.sol";
|
||||
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract DeployL2BridgeProxyPlaceholder is Script {
|
||||
uint256 L2_DEPLOYER_PRIVATE_KEY = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
|
||||
|
||||
ProxyAdmin proxyAdmin;
|
||||
EmptyContract placeholder;
|
||||
|
||||
function run() external {
|
||||
vm.startBroadcast(L2_DEPLOYER_PRIVATE_KEY);
|
||||
|
||||
// upgradable
|
||||
deployProxyAdmin();
|
||||
deployPlaceHolder();
|
||||
deployL2ScrollMessenger();
|
||||
deployL2ETHGateway();
|
||||
deployL2WETHGateway();
|
||||
deployL2StandardERC20Gateway();
|
||||
deployL2CustomERC20Gateway();
|
||||
deployL2ERC721Gateway();
|
||||
deployL2ERC1155Gateway();
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
function deployProxyAdmin() internal {
|
||||
proxyAdmin = new ProxyAdmin();
|
||||
|
||||
logAddress("L2_PROXY_ADMIN_ADDR", address(proxyAdmin));
|
||||
}
|
||||
|
||||
function deployPlaceHolder() internal {
|
||||
placeholder = new EmptyContract();
|
||||
|
||||
logAddress("L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR", address(placeholder));
|
||||
}
|
||||
|
||||
function deployL2ScrollMessenger() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_SCROLL_MESSENGER_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2StandardERC20Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2ETHGateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_ETH_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2WETHGateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_WETH_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2CustomERC20Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2ERC721Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
logAddress("L2_ERC721_GATEWAY_PROXY_ADDR", address(proxy));
|
||||
}
|
||||
|
||||
function deployL2ERC1155Gateway() internal {
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(placeholder),
|
||||
address(proxyAdmin),
|
||||
new bytes(0)
|
||||
);
|
||||
|
||||
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)))));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
|
||||
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
|
||||
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.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";
|
||||
@@ -17,14 +14,9 @@ import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol";
|
||||
import {MultipleVersionRollupVerifier} from "../../src/L1/rollup/MultipleVersionRollupVerifier.sol";
|
||||
import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
|
||||
import {L1MessageQueue} from "../../src/L1/rollup/L1MessageQueue.sol";
|
||||
import {L1MessageQueueWithGasPriceOracle} from "../../src/L1/rollup/L1MessageQueueWithGasPriceOracle.sol";
|
||||
import {L2GasPriceOracle} from "../../src/L1/rollup/L2GasPriceOracle.sol";
|
||||
import {EnforcedTxGateway} from "../../src/L1/gateways/EnforcedTxGateway.sol";
|
||||
|
||||
// solhint-disable max-states-count
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract InitializeL1BridgeContracts is Script {
|
||||
uint256 L1_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_DEPLOYER_PRIVATE_KEY");
|
||||
|
||||
@@ -36,34 +28,23 @@ contract InitializeL1BridgeContracts is Script {
|
||||
address L1_FEE_VAULT_ADDR = vm.envAddress("L1_FEE_VAULT_ADDR");
|
||||
address L1_WETH_ADDR = vm.envAddress("L1_WETH_ADDR");
|
||||
|
||||
address L1_PROXY_ADMIN_ADDR = vm.envAddress("L1_PROXY_ADMIN_ADDR");
|
||||
|
||||
address L1_WHITELIST_ADDR = vm.envAddress("L1_WHITELIST_ADDR");
|
||||
address L1_SCROLL_CHAIN_PROXY_ADDR = vm.envAddress("L1_SCROLL_CHAIN_PROXY_ADDR");
|
||||
address L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR = vm.envAddress("L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR");
|
||||
address L1_MESSAGE_QUEUE_PROXY_ADDR = vm.envAddress("L1_MESSAGE_QUEUE_PROXY_ADDR");
|
||||
address L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR = vm.envAddress("L1_MESSAGE_QUEUE_IMPLEMENTATION_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_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = vm.envAddress("L1_SCROLL_MESSENGER_IMPLEMENTATION_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_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L1_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC721_GATEWAY_PROXY_ADDR");
|
||||
address L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L1_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ERC1155_GATEWAY_PROXY_ADDR");
|
||||
address L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L1_ETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ETH_GATEWAY_PROXY_ADDR");
|
||||
address L1_ETH_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L1_ETH_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
|
||||
address L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR =
|
||||
vm.envAddress("L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L1_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_WETH_GATEWAY_PROXY_ADDR");
|
||||
address L1_WETH_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L1_WETH_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR = vm.envAddress("L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR");
|
||||
address L1_ENFORCED_TX_GATEWAY_PROXY_ADDR = vm.envAddress("L1_ENFORCED_TX_GATEWAY_PROXY_ADDR");
|
||||
|
||||
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");
|
||||
@@ -74,18 +55,13 @@ contract InitializeL1BridgeContracts is Script {
|
||||
address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR");
|
||||
|
||||
function run() external {
|
||||
ProxyAdmin proxyAdmin = ProxyAdmin(L1_PROXY_ADMIN_ADDR);
|
||||
|
||||
vm.startBroadcast(L1_DEPLOYER_PRIVATE_KEY);
|
||||
|
||||
// initialize ScrollChain
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_SCROLL_CHAIN_PROXY_ADDR),
|
||||
L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
ScrollChain.initialize,
|
||||
(L1_MESSAGE_QUEUE_PROXY_ADDR, L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR, MAX_TX_IN_CHUNK)
|
||||
)
|
||||
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).initialize(
|
||||
L1_MESSAGE_QUEUE_PROXY_ADDR,
|
||||
L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR,
|
||||
MAX_TX_IN_CHUNK
|
||||
);
|
||||
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addSequencer(L1_COMMIT_SENDER_ADDRESS);
|
||||
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addProver(L1_FINALIZE_SENDER_ADDRESS);
|
||||
@@ -102,36 +78,21 @@ contract InitializeL1BridgeContracts is Script {
|
||||
);
|
||||
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).updateWhitelist(L1_WHITELIST_ADDR);
|
||||
|
||||
// initialize L1MessageQueueWithGasPriceOracle
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_MESSAGE_QUEUE_PROXY_ADDR),
|
||||
L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L1MessageQueue.initialize,
|
||||
(
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L1_SCROLL_CHAIN_PROXY_ADDR,
|
||||
L1_ENFORCED_TX_GATEWAY_PROXY_ADDR,
|
||||
L2_GAS_PRICE_ORACLE_PROXY_ADDR,
|
||||
MAX_L1_MESSAGE_GAS_LIMIT
|
||||
)
|
||||
)
|
||||
// initialize L1MessageQueue
|
||||
L1MessageQueue(L1_MESSAGE_QUEUE_PROXY_ADDR).initialize(
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L1_SCROLL_CHAIN_PROXY_ADDR,
|
||||
L1_ENFORCED_TX_GATEWAY_PROXY_ADDR,
|
||||
L2_GAS_PRICE_ORACLE_PROXY_ADDR,
|
||||
MAX_L1_MESSAGE_GAS_LIMIT
|
||||
);
|
||||
L1MessageQueueWithGasPriceOracle(L1_MESSAGE_QUEUE_PROXY_ADDR).initializeV2();
|
||||
|
||||
// initialize L1ScrollMessenger
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_SCROLL_MESSENGER_PROXY_ADDR),
|
||||
L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L1ScrollMessenger.initialize,
|
||||
(
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L1_FEE_VAULT_ADDR,
|
||||
L1_SCROLL_CHAIN_PROXY_ADDR,
|
||||
L1_MESSAGE_QUEUE_PROXY_ADDR
|
||||
)
|
||||
)
|
||||
L1ScrollMessenger(payable(L1_SCROLL_MESSENGER_PROXY_ADDR)).initialize(
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L1_FEE_VAULT_ADDR,
|
||||
L1_SCROLL_CHAIN_PROXY_ADDR,
|
||||
L1_MESSAGE_QUEUE_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize EnforcedTxGateway
|
||||
@@ -147,63 +108,45 @@ contract InitializeL1BridgeContracts is Script {
|
||||
);
|
||||
|
||||
// initialize L1CustomERC20Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR),
|
||||
L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L1CustomERC20Gateway.initialize,
|
||||
(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR, L1_GATEWAY_ROUTER_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR)
|
||||
)
|
||||
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 L1ERC1155Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_ERC1155_GATEWAY_PROXY_ADDR),
|
||||
L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(L1ERC1155Gateway.initialize, (L2_ERC1155_GATEWAY_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR))
|
||||
L1ERC1155Gateway(L1_ERC1155_GATEWAY_PROXY_ADDR).initialize(
|
||||
L2_ERC1155_GATEWAY_PROXY_ADDR,
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize L1ERC721Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_ERC721_GATEWAY_PROXY_ADDR),
|
||||
L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(L1ERC721Gateway.initialize, (L2_ERC721_GATEWAY_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR))
|
||||
L1ERC721Gateway(L1_ERC721_GATEWAY_PROXY_ADDR).initialize(
|
||||
L2_ERC721_GATEWAY_PROXY_ADDR,
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize L1ETHGateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_ETH_GATEWAY_PROXY_ADDR),
|
||||
L1_ETH_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L1ETHGateway.initialize,
|
||||
(L2_ETH_GATEWAY_PROXY_ADDR, L1_GATEWAY_ROUTER_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR)
|
||||
)
|
||||
L1ETHGateway(L1_ETH_GATEWAY_PROXY_ADDR).initialize(
|
||||
L2_ETH_GATEWAY_PROXY_ADDR,
|
||||
L1_GATEWAY_ROUTER_PROXY_ADDR,
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize L1StandardERC20Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR),
|
||||
L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L1StandardERC20Gateway.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
|
||||
)
|
||||
)
|
||||
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
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L1_WETH_GATEWAY_PROXY_ADDR),
|
||||
L1_WETH_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L1WETHGateway.initialize,
|
||||
(L2_WETH_GATEWAY_PROXY_ADDR, L1_GATEWAY_ROUTER_PROXY_ADDR, L1_SCROLL_MESSENGER_PROXY_ADDR)
|
||||
)
|
||||
L1WETHGateway(payable(L1_WETH_GATEWAY_PROXY_ADDR)).initialize(
|
||||
L2_WETH_GATEWAY_PROXY_ADDR,
|
||||
L1_GATEWAY_ROUTER_PROXY_ADDR,
|
||||
L1_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// set WETH gateway in router
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
|
||||
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
|
||||
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
|
||||
|
||||
import {L2ScrollMessenger} from "../../src/L2/L2ScrollMessenger.sol";
|
||||
import {L2CustomERC20Gateway} from "../../src/L2/gateways/L2CustomERC20Gateway.sol";
|
||||
import {L2ERC1155Gateway} from "../../src/L2/gateways/L2ERC1155Gateway.sol";
|
||||
@@ -20,15 +17,10 @@ import {L1GasPriceOracle} from "../../src/L2/predeploys/L1GasPriceOracle.sol";
|
||||
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
|
||||
import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
|
||||
|
||||
// solhint-disable max-states-count
|
||||
// solhint-disable state-visibility
|
||||
// solhint-disable var-name-mixedcase
|
||||
|
||||
contract InitializeL2BridgeContracts is Script {
|
||||
uint256 deployerPrivateKey = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
|
||||
|
||||
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
|
||||
address L2_PROXY_ADMIN_ADDR = vm.envAddress("L2_PROXY_ADMIN_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");
|
||||
@@ -45,26 +37,16 @@ contract InitializeL2BridgeContracts is Script {
|
||||
address L2_MESSAGE_QUEUE_ADDR = vm.envAddress("L2_MESSAGE_QUEUE_ADDR");
|
||||
|
||||
address L2_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_PROXY_ADDR");
|
||||
address L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR = vm.envAddress("L2_SCROLL_MESSENGER_IMPLEMENTATION_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_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L2_ERC721_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC721_GATEWAY_PROXY_ADDR");
|
||||
address L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L2_ERC1155_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ERC1155_GATEWAY_PROXY_ADDR");
|
||||
address L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L2_ETH_GATEWAY_PROXY_ADDR = vm.envAddress("L2_ETH_GATEWAY_PROXY_ADDR");
|
||||
address L2_ETH_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L2_ETH_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR");
|
||||
address L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR =
|
||||
vm.envAddress("L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L2_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L2_WETH_GATEWAY_PROXY_ADDR");
|
||||
address L2_WETH_GATEWAY_IMPLEMENTATION_ADDR = vm.envAddress("L2_WETH_GATEWAY_IMPLEMENTATION_ADDR");
|
||||
address L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR = vm.envAddress("L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR");
|
||||
|
||||
function run() external {
|
||||
ProxyAdmin proxyAdmin = ProxyAdmin(L2_PROXY_ADMIN_ADDR);
|
||||
|
||||
vm.startBroadcast(deployerPrivateKey);
|
||||
|
||||
// initialize L2MessageQueue
|
||||
@@ -77,11 +59,7 @@ contract InitializeL2BridgeContracts is Script {
|
||||
L1GasPriceOracle(L1_GAS_PRICE_ORACLE_ADDR).updateWhitelist(L2_WHITELIST_ADDR);
|
||||
|
||||
// initialize L2ScrollMessenger
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_SCROLL_MESSENGER_PROXY_ADDR),
|
||||
L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(L2ScrollMessenger.initialize, (L1_SCROLL_MESSENGER_PROXY_ADDR))
|
||||
);
|
||||
L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).initialize(L1_SCROLL_MESSENGER_PROXY_ADDR);
|
||||
|
||||
// initialize L2GatewayRouter
|
||||
L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).initialize(
|
||||
@@ -90,62 +68,44 @@ contract InitializeL2BridgeContracts is Script {
|
||||
);
|
||||
|
||||
// initialize L2CustomERC20Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR),
|
||||
L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L2CustomERC20Gateway.initialize,
|
||||
(L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR, L2_GATEWAY_ROUTER_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR)
|
||||
)
|
||||
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
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_ERC1155_GATEWAY_PROXY_ADDR),
|
||||
L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(L2ERC1155Gateway.initialize, (L1_ERC1155_GATEWAY_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR))
|
||||
L2ERC1155Gateway(L2_ERC1155_GATEWAY_PROXY_ADDR).initialize(
|
||||
L1_ERC1155_GATEWAY_PROXY_ADDR,
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize L2ERC721Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_ERC721_GATEWAY_PROXY_ADDR),
|
||||
L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(L2ERC721Gateway.initialize, (L1_ERC721_GATEWAY_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR))
|
||||
L2ERC721Gateway(L2_ERC721_GATEWAY_PROXY_ADDR).initialize(
|
||||
L1_ERC721_GATEWAY_PROXY_ADDR,
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize L2ETHGateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_ETH_GATEWAY_PROXY_ADDR),
|
||||
L2_ETH_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L2ETHGateway.initialize,
|
||||
(L1_ETH_GATEWAY_PROXY_ADDR, L2_GATEWAY_ROUTER_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR)
|
||||
)
|
||||
L2ETHGateway(L2_ETH_GATEWAY_PROXY_ADDR).initialize(
|
||||
L1_ETH_GATEWAY_PROXY_ADDR,
|
||||
L2_GATEWAY_ROUTER_PROXY_ADDR,
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// initialize L2StandardERC20Gateway
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR),
|
||||
L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L2StandardERC20Gateway.initialize,
|
||||
(
|
||||
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR,
|
||||
L2_GATEWAY_ROUTER_PROXY_ADDR,
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR,
|
||||
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR
|
||||
)
|
||||
)
|
||||
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
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(L2_WETH_GATEWAY_PROXY_ADDR),
|
||||
L2_WETH_GATEWAY_IMPLEMENTATION_ADDR,
|
||||
abi.encodeCall(
|
||||
L2WETHGateway.initialize,
|
||||
(L1_WETH_GATEWAY_PROXY_ADDR, L2_GATEWAY_ROUTER_PROXY_ADDR, L2_SCROLL_MESSENGER_PROXY_ADDR)
|
||||
)
|
||||
L2WETHGateway(payable(L2_WETH_GATEWAY_PROXY_ADDR)).initialize(
|
||||
L1_WETH_GATEWAY_PROXY_ADDR,
|
||||
L2_GATEWAY_ROUTER_PROXY_ADDR,
|
||||
L2_SCROLL_MESSENGER_PROXY_ADDR
|
||||
);
|
||||
|
||||
// set WETH gateway in router
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity =0.8.16;
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
|
||||
|
||||
@@ -27,16 +27,6 @@ import {IMessageDropCallback} from "../libraries/callbacks/IMessageDropCallback.
|
||||
/// @dev All deposited Ether (including `WETH` deposited throng `L1WETHGateway`) will locked in
|
||||
/// this contract.
|
||||
contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
/*************
|
||||
* Constants *
|
||||
*************/
|
||||
|
||||
/// @notice The address of Rollup contract.
|
||||
address public immutable rollup;
|
||||
|
||||
/// @notice The address of L1MessageQueue contract.
|
||||
address public immutable messageQueue;
|
||||
|
||||
/***********
|
||||
* Structs *
|
||||
***********/
|
||||
@@ -61,11 +51,11 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
/// @notice Mapping from L1 message hash to drop status.
|
||||
mapping(bytes32 => bool) public isL1MessageDropped;
|
||||
|
||||
/// @dev The storage slot used as Rollup contract, which is deprecated now.
|
||||
address private __rollup;
|
||||
/// @notice The address of Rollup contract.
|
||||
address public rollup;
|
||||
|
||||
/// @dev The storage slot used as L1MessageQueue contract, which is deprecated now.
|
||||
address private __messageQueue;
|
||||
/// @notice The address of L1MessageQueue contract.
|
||||
address public messageQueue;
|
||||
|
||||
/// @notice The maximum number of times each L1 message can be replayed.
|
||||
uint256 public maxReplayTimes;
|
||||
@@ -90,25 +80,11 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
constructor(
|
||||
address _counterpart,
|
||||
address _rollup,
|
||||
address _messageQueue
|
||||
) ScrollMessengerBase(_counterpart) {
|
||||
if (_rollup == address(0) || _messageQueue == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
|
||||
rollup = _rollup;
|
||||
messageQueue = _messageQueue;
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1ScrollMessenger.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_rollup` and `_messageQueue` are no longer used.
|
||||
///
|
||||
/// @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.
|
||||
@@ -119,10 +95,13 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
address _rollup,
|
||||
address _messageQueue
|
||||
) public initializer {
|
||||
if (_counterpart == address(0) || _rollup == address(0) || _messageQueue == address(0)) {
|
||||
revert ErrZeroAddress();
|
||||
}
|
||||
ScrollMessengerBase.__ScrollMessengerBase_init(_counterpart, _feeVault);
|
||||
|
||||
__rollup = _rollup;
|
||||
__messageQueue = _messageQueue;
|
||||
rollup = _rollup;
|
||||
messageQueue = _messageQueue;
|
||||
|
||||
maxReplayTimes = 3;
|
||||
emit UpdateMaxReplayTimes(0, 3);
|
||||
@@ -166,8 +145,9 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
require(!isL2MessageExecuted[_xDomainCalldataHash], "Message was already successfully executed");
|
||||
|
||||
{
|
||||
require(IScrollChain(rollup).isBatchFinalized(_proof.batchIndex), "Batch is not finalized");
|
||||
bytes32 _messageRoot = IScrollChain(rollup).withdrawRoots(_proof.batchIndex);
|
||||
address _rollup = rollup;
|
||||
require(IScrollChain(_rollup).isBatchFinalized(_proof.batchIndex), "Batch is not finalized");
|
||||
bytes32 _messageRoot = IScrollChain(_rollup).withdrawRoots(_proof.batchIndex);
|
||||
require(
|
||||
WithdrawTrieVerifier.verifyMerkleProof(_messageRoot, _xDomainCalldataHash, _nonce, _proof.merkleProof),
|
||||
"Invalid proof"
|
||||
@@ -208,6 +188,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
// is encoded in the `_message`. We will check the `xDomainCalldata` on layer 2 to avoid duplicated execution.
|
||||
// So, only one message will succeed on layer 2. If one of the message is executed successfully, the other one
|
||||
// will revert with "Message was already successfully executed".
|
||||
address _messageQueue = messageQueue;
|
||||
address _counterpart = counterpart;
|
||||
bytes memory _xDomainCalldata = _encodeXDomainCalldata(_from, _to, _value, _messageNonce, _message);
|
||||
bytes32 _xDomainCalldataHash = keccak256(_xDomainCalldata);
|
||||
|
||||
@@ -216,7 +198,7 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
require(!isL1MessageDropped[_xDomainCalldataHash], "Message already dropped");
|
||||
|
||||
// compute and deduct the messaging fee to fee vault.
|
||||
uint256 _fee = IL1MessageQueue(messageQueue).estimateCrossDomainMessageFee(_newGasLimit);
|
||||
uint256 _fee = IL1MessageQueue(_messageQueue).estimateCrossDomainMessageFee(_newGasLimit);
|
||||
|
||||
// charge relayer fee
|
||||
require(msg.value >= _fee, "Insufficient msg.value for fee");
|
||||
@@ -226,8 +208,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
}
|
||||
|
||||
// enqueue the new transaction
|
||||
uint256 _nextQueueIndex = IL1MessageQueue(messageQueue).nextCrossDomainMessageIndex();
|
||||
IL1MessageQueue(messageQueue).appendCrossDomainMessage(counterpart, _newGasLimit, _xDomainCalldata);
|
||||
uint256 _nextQueueIndex = IL1MessageQueue(_messageQueue).nextCrossDomainMessageIndex();
|
||||
IL1MessageQueue(_messageQueue).appendCrossDomainMessage(_counterpart, _newGasLimit, _xDomainCalldata);
|
||||
|
||||
ReplayState memory _replayState = replayStates[_xDomainCalldataHash];
|
||||
// update the replayed message chain.
|
||||
@@ -278,6 +260,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
//
|
||||
// We limit the number of `replayMessage` calls of each message, which may solve the above problem.
|
||||
|
||||
address _messageQueue = messageQueue;
|
||||
|
||||
// check message exists
|
||||
bytes memory _xDomainCalldata = _encodeXDomainCalldata(_from, _to, _value, _messageNonce, _message);
|
||||
bytes32 _xDomainCalldataHash = keccak256(_xDomainCalldata);
|
||||
@@ -293,7 +277,7 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
// check message is skipped and drop it.
|
||||
// @note If the list is very long, the message may never be dropped.
|
||||
while (true) {
|
||||
IL1MessageQueue(messageQueue).dropCrossDomainMessage(_lastIndex);
|
||||
IL1MessageQueue(_messageQueue).dropCrossDomainMessage(_lastIndex);
|
||||
_lastIndex = prevReplayIndex[_lastIndex];
|
||||
if (_lastIndex == 0) break;
|
||||
unchecked {
|
||||
@@ -335,12 +319,15 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
uint256 _gasLimit,
|
||||
address _refundAddress
|
||||
) internal nonReentrant {
|
||||
address _messageQueue = messageQueue; // gas saving
|
||||
address _counterpart = counterpart; // gas saving
|
||||
|
||||
// compute the actual cross domain message calldata.
|
||||
uint256 _messageNonce = IL1MessageQueue(messageQueue).nextCrossDomainMessageIndex();
|
||||
uint256 _messageNonce = IL1MessageQueue(_messageQueue).nextCrossDomainMessageIndex();
|
||||
bytes memory _xDomainCalldata = _encodeXDomainCalldata(_msgSender(), _to, _value, _messageNonce, _message);
|
||||
|
||||
// compute and deduct the messaging fee to fee vault.
|
||||
uint256 _fee = IL1MessageQueue(messageQueue).estimateCrossDomainMessageFee(_gasLimit);
|
||||
uint256 _fee = IL1MessageQueue(_messageQueue).estimateCrossDomainMessageFee(_gasLimit);
|
||||
require(msg.value >= _fee + _value, "Insufficient msg.value");
|
||||
if (_fee > 0) {
|
||||
(bool _success, ) = feeVault.call{value: _fee}("");
|
||||
@@ -348,7 +335,7 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
|
||||
}
|
||||
|
||||
// append message to L1MessageQueue
|
||||
IL1MessageQueue(messageQueue).appendCrossDomainMessage(counterpart, _gasLimit, _xDomainCalldata);
|
||||
IL1MessageQueue(_messageQueue).appendCrossDomainMessage(_counterpart, _gasLimit, _xDomainCalldata);
|
||||
|
||||
// record the message hash for future use.
|
||||
bytes32 _xDomainCalldataHash = keccak256(_xDomainCalldata);
|
||||
|
||||
134
contracts/src/L1/ecc.sol
Normal file
134
contracts/src/L1/ecc.sol
Normal file
@@ -0,0 +1,134 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
contract Ecc {
|
||||
/* ECC Functions */
|
||||
// https://etherscan.io/address/0x41bf00f080ed41fa86201eac56b8afb170d9e36d#code
|
||||
function ecAdd(uint256[2] memory p0, uint256[2] memory p1) public view
|
||||
returns (uint256[2] memory retP)
|
||||
{
|
||||
uint256[4] memory i = [p0[0], p0[1], p1[0], p1[1]];
|
||||
|
||||
assembly {
|
||||
// call ecadd precompile
|
||||
// inputs are: x1, y1, x2, y2
|
||||
if iszero(staticcall(not(0), 0x06, i, 0x80, retP, 0x40)) {
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://etherscan.io/address/0x41bf00f080ed41fa86201eac56b8afb170d9e36d#code
|
||||
function ecMul(uint256[2] memory p, uint256 s) public view
|
||||
returns (uint256[2] memory retP)
|
||||
{
|
||||
// With a public key (x, y), this computes p = scalar * (x, y).
|
||||
uint256[3] memory i = [p[0], p[1], s];
|
||||
|
||||
assembly {
|
||||
// call ecmul precompile
|
||||
// inputs are: x, y, scalar
|
||||
if iszero(staticcall(not(0), 0x07, i, 0x60, retP, 0x40)) {
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scroll-tech/scroll/contracts/src/libraries/verifier/RollupVerifier.sol
|
||||
struct G1Point {
|
||||
uint256 x;
|
||||
uint256 y;
|
||||
}
|
||||
struct G2Point {
|
||||
uint256[2] x;
|
||||
uint256[2] y;
|
||||
}
|
||||
function ecPairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) {
|
||||
uint256 length = p1.length * 6;
|
||||
uint256[] memory input = new uint256[](length);
|
||||
uint256[1] memory result;
|
||||
bool ret;
|
||||
|
||||
require(p1.length == p2.length);
|
||||
|
||||
for (uint256 i = 0; i < p1.length; i++) {
|
||||
input[0 + i * 6] = p1[i].x;
|
||||
input[1 + i * 6] = p1[i].y;
|
||||
input[2 + i * 6] = p2[i].x[0];
|
||||
input[3 + i * 6] = p2[i].x[1];
|
||||
input[4 + i * 6] = p2[i].y[0];
|
||||
input[5 + i * 6] = p2[i].y[1];
|
||||
}
|
||||
|
||||
assembly {
|
||||
ret := staticcall(gas(), 8, add(input, 0x20), mul(length, 0x20), result, 0x20)
|
||||
}
|
||||
require(ret);
|
||||
return result[0] != 0;
|
||||
}
|
||||
|
||||
/* Bench */
|
||||
function ecAdds(uint256 n) public
|
||||
{
|
||||
uint256[2] memory p0;
|
||||
p0[0] = 1;
|
||||
p0[1] = 2;
|
||||
uint256[2] memory p1;
|
||||
p1[0] = 1;
|
||||
p1[1] = 2;
|
||||
|
||||
for (uint i = 0; i < n; i++) {
|
||||
ecAdd(p0, p1);
|
||||
}
|
||||
}
|
||||
|
||||
function ecMuls(uint256 n) public
|
||||
{
|
||||
uint256[2] memory p0;
|
||||
p0[0] = 1;
|
||||
p0[1] = 2;
|
||||
|
||||
for (uint i = 0; i < n; i++) {
|
||||
ecMul(p0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
function ecPairings(uint256 n) public
|
||||
{
|
||||
G1Point[] memory g1_points = new G1Point[](2);
|
||||
G2Point[] memory g2_points = new G2Point[](2);
|
||||
g1_points[0].x = 0x0000000000000000000000000000000000000000000000000000000000000001;
|
||||
g1_points[0].y = 0x0000000000000000000000000000000000000000000000000000000000000002;
|
||||
g2_points[0].x[1] = 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed;
|
||||
g2_points[0].x[0] = 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2;
|
||||
g2_points[0].y[1] = 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa;
|
||||
g2_points[0].y[0] = 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b;
|
||||
g1_points[1].x = 0x1aa125a22bd902874034e67868aed40267e5575d5919677987e3bc6dd42a32fe;
|
||||
g1_points[1].y = 0x1bacc186725464068956d9a191455c2d6f6db282d83645c610510d8d4efbaee0;
|
||||
g2_points[1].x[1] = 0x1b7734c80605f71f1e2de61e998ce5854ff2abebb76537c3d67e50d71422a852;
|
||||
g2_points[1].x[0] = 0x10d5a1e34b2388a5ebe266033a5e0e63c89084203784da0c6bd9b052a78a2cac;
|
||||
g2_points[1].y[1] = 0x275739c5c2cdbc72e37c689e2ab441ea76c1d284b9c46ae8f5c42ead937819e1;
|
||||
g2_points[1].y[0] = 0x018de34c5b7c3d3d75428bbe050f1449ea3d9961d563291f307a1874f7332e65;
|
||||
|
||||
for (uint i = 0; i < n; i++) {
|
||||
ecPairing(g1_points, g2_points);
|
||||
// bool checked = false;
|
||||
// checked = ecPairing(g1_points, g2_points);
|
||||
// require(checked);
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8a0b7bed82d6b8053872c3fd40703efd58f5699d/test/utils/cryptography/ECDSA.test.js#L230
|
||||
function ecRecovers(uint256 n) public
|
||||
{
|
||||
bytes32 hash = 0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9;
|
||||
bytes32 r = 0xe742ff452d41413616a5bf43fe15dd88294e983d3d36206c2712f39083d638bd;
|
||||
uint8 v = 0x1b;
|
||||
bytes32 s = 0xe0a0fc89be718fbc1033e1d30d78be1c68081562ed2e97af876f286f3453231d;
|
||||
|
||||
for (uint i = 0; i < n; i++) {
|
||||
ecrecover(hash, v, r, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,24 +41,11 @@ contract L1CustomERC20Gateway is L1ERC20Gateway {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1CustomERC20Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L2USDCGateway` contract in L2.
|
||||
/// @param _router The address of `L1GatewayRouter` contract.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_router == address(0)) revert ErrorZeroAddress();
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1CustomERC20Gateway.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L2CustomERC20Gateway in L2.
|
||||
/// @param _router The address of L1GatewayRouter.
|
||||
/// @param _messenger The address of L1ScrollMessenger.
|
||||
@@ -67,6 +54,8 @@ contract L1CustomERC20Gateway is L1ERC20Gateway {
|
||||
address _router,
|
||||
address _messenger
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
}
|
||||
|
||||
|
||||
11
contracts/src/L1/gateways/L1DAIGateway.sol
Normal file
11
contracts/src/L1/gateways/L1DAIGateway.sol
Normal file
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
import {L1CustomERC20Gateway} from "./L1CustomERC20Gateway.sol";
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
|
||||
contract L1DAIGateway is L1CustomERC20Gateway {
|
||||
|
||||
}
|
||||
@@ -41,11 +41,7 @@ contract L1ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL1ERC
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1ERC1155Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L1ERC1155Gateway` contract in L2.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(address _counterpart, address _messenger) ScrollGatewayBase(_counterpart, address(0), _messenger) {
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,18 +41,11 @@ contract L1ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL1ERC72
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L2ERC721Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L2ERC721Gateway` contract in L2.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(address _counterpart, address _messenger) ScrollGatewayBase(_counterpart, address(0), _messenger) {
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1ERC721Gateway.
|
||||
///
|
||||
/// @dev The parameters `_counterpart` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L2ERC721Gateway in L2.
|
||||
/// @param _messenger The address of L1ScrollMessenger.
|
||||
function initialize(address _counterpart, address _messenger) external initializer {
|
||||
|
||||
@@ -21,25 +21,11 @@ contract L1ETHGateway is ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1ETHGateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L2ETHGateway` contract in L2.
|
||||
/// @param _router The address of `L1GatewayRouter` contract.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_router == address(0)) revert ErrorZeroAddress();
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1ETHGateway.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L2ETHGateway in L2.
|
||||
/// @param _router The address of L1GatewayRouter.
|
||||
/// @param _messenger The address of L1ScrollMessenger.
|
||||
@@ -48,6 +34,7 @@ contract L1ETHGateway is ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback
|
||||
address _router,
|
||||
address _messenger
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
}
|
||||
|
||||
@@ -133,12 +120,9 @@ contract L1ETHGateway is ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback
|
||||
|
||||
// 1. Extract real sender if this call is from L1GatewayRouter.
|
||||
address _from = _msgSender();
|
||||
|
||||
/* comment out since router won't use this contract anymore
|
||||
if (router == _from) {
|
||||
(_from, _data) = abi.decode(_data, (address, bytes));
|
||||
}
|
||||
*/
|
||||
|
||||
// @note no rate limit here, since ETH is limited in messenger
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
|
||||
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
|
||||
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
|
||||
|
||||
import {IL1ScrollMessenger} from "../IL1ScrollMessenger.sol";
|
||||
import {IL1ETHGateway} from "./IL1ETHGateway.sol";
|
||||
import {IL1ERC20Gateway} from "./IL1ERC20Gateway.sol";
|
||||
import {IL1GatewayRouter} from "./IL1GatewayRouter.sol";
|
||||
@@ -19,26 +18,11 @@ import {IL1GatewayRouter} from "./IL1GatewayRouter.sol";
|
||||
contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
|
||||
using SafeERC20Upgradeable for IERC20Upgradeable;
|
||||
|
||||
/**********
|
||||
* Errors *
|
||||
**********/
|
||||
|
||||
/// @dev Thrown when the given address is `address(0)`.
|
||||
error ErrorZeroAddress();
|
||||
|
||||
/*************
|
||||
* Constants *
|
||||
*************/
|
||||
|
||||
/// @notice The address of `L1ScrollMessenger`.
|
||||
address public immutable messenger;
|
||||
|
||||
/*************
|
||||
* Variables *
|
||||
*************/
|
||||
|
||||
/// @notice The address of L1ETHGateway.
|
||||
/// @dev This variable is no longer used.
|
||||
address public ethGateway;
|
||||
|
||||
/// @notice The addess of default ERC20 gateway, normally the L1StandardERC20Gateway contract.
|
||||
@@ -69,18 +53,11 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
constructor(address _messenger) {
|
||||
if (_messenger == address(0)) revert ErrorZeroAddress();
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
|
||||
messenger = _messenger;
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1GatewayRouter.
|
||||
///
|
||||
/// @dev The parameters `_ethGateway` is no longer used.
|
||||
///
|
||||
/// @param _ethGateway The address of L1ETHGateway contract.
|
||||
/// @param _defaultERC20Gateway The address of default ERC20 Gateway contract.
|
||||
function initialize(address _ethGateway, address _defaultERC20Gateway) external initializer {
|
||||
@@ -223,7 +200,13 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
|
||||
bytes memory _data,
|
||||
uint256 _gasLimit
|
||||
) public payable override onlyNotInContext {
|
||||
IL1ScrollMessenger(messenger).sendMessage{value: msg.value}(_to, _amount, _data, _gasLimit, _msgSender());
|
||||
address _gateway = ethGateway;
|
||||
require(_gateway != address(0), "eth gateway available");
|
||||
|
||||
// encode msg.sender with _data
|
||||
bytes memory _routerData = abi.encode(_msgSender(), _data);
|
||||
|
||||
IL1ETHGateway(_gateway).depositETHAndCall{value: msg.value}(_to, _amount, _routerData, _gasLimit);
|
||||
}
|
||||
|
||||
/// @inheritdoc IL1ETHGateway
|
||||
|
||||
@@ -19,25 +19,15 @@ import {L1ERC20Gateway} from "./L1ERC20Gateway.sol";
|
||||
/// token will be transfer to the recipient directly. Any ERC20 that requires non-standard functionality
|
||||
/// should use a separate gateway.
|
||||
contract L1StandardERC20Gateway is L1ERC20Gateway {
|
||||
/*************
|
||||
* Constants *
|
||||
*************/
|
||||
|
||||
/// @notice The address of ScrollStandardERC20 implementation in L2.
|
||||
address public immutable l2TokenImplementation;
|
||||
|
||||
/// @notice The address of ScrollStandardERC20Factory contract in L2.
|
||||
address public immutable l2TokenFactory;
|
||||
|
||||
/*************
|
||||
* Variables *
|
||||
*************/
|
||||
|
||||
/// @dev The storage slot used as ScrollStandardERC20 implementation in L2, which is deprecated now.
|
||||
address private __l2TokenImplementation;
|
||||
/// @notice The address of ScrollStandardERC20 implementation in L2.
|
||||
address public l2TokenImplementation;
|
||||
|
||||
/// @dev The storage slot used as ScrollStandardERC20Factory contract in L2, which is deprecated now.
|
||||
address private __l2TokenFactory;
|
||||
/// @notice The address of ScrollStandardERC20Factory contract in L2.
|
||||
address public l2TokenFactory;
|
||||
|
||||
/// @notice Mapping from l1 token address to l2 token address.
|
||||
/// @dev This is not necessary, since we can compute the address directly. But, we use this mapping
|
||||
@@ -49,35 +39,11 @@ contract L1StandardERC20Gateway is L1ERC20Gateway {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1StandardERC20Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L2StandardERC20Gateway` contract in L2.
|
||||
/// @param _router The address of `L1GatewayRouter` contract.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
/// @param _l2TokenImplementation The address of `ScrollStandardERC20` implementation in L2.
|
||||
/// @param _l2TokenFactory The address of `ScrollStandardERC20Factory` contract in L2.
|
||||
constructor(
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger,
|
||||
address _l2TokenImplementation,
|
||||
address _l2TokenFactory
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_router == address(0) || _l2TokenImplementation == address(0) || _l2TokenFactory == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
|
||||
l2TokenImplementation = _l2TokenImplementation;
|
||||
l2TokenFactory = _l2TokenFactory;
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1StandardERC20Gateway.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router`, `_messenger`, `_l2TokenImplementation` and
|
||||
/// `_l2TokenFactory` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L2StandardERC20Gateway in L2.
|
||||
/// @param _router The address of L1GatewayRouter.
|
||||
/// @param _messenger The address of L1ScrollMessenger.
|
||||
@@ -90,10 +56,14 @@ contract L1StandardERC20Gateway is L1ERC20Gateway {
|
||||
address _l2TokenImplementation,
|
||||
address _l2TokenFactory
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
|
||||
__l2TokenImplementation = _l2TokenImplementation;
|
||||
__l2TokenFactory = _l2TokenFactory;
|
||||
require(_l2TokenImplementation != address(0), "zero implementation hash");
|
||||
require(_l2TokenFactory != address(0), "zero factory address");
|
||||
|
||||
l2TokenImplementation = _l2TokenImplementation;
|
||||
l2TokenFactory = _l2TokenFactory;
|
||||
}
|
||||
|
||||
/*************************
|
||||
|
||||
@@ -33,24 +33,7 @@ contract L1WETHGateway is L1ERC20Gateway {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1WETHGateway` implementation contract.
|
||||
///
|
||||
/// @param _WETH The address of WETH in L1.
|
||||
/// @param _l2WETH The address of WETH in L2.
|
||||
/// @param _counterpart The address of `L2WETHGateway` contract in L2.
|
||||
/// @param _router The address of `L1GatewayRouter` contract.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(
|
||||
address _WETH,
|
||||
address _l2WETH,
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_WETH == address(0) || _l2WETH == address(0) || _router == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
|
||||
constructor(address _WETH, address _l2WETH) {
|
||||
_disableInitializers();
|
||||
|
||||
WETH = _WETH;
|
||||
@@ -66,6 +49,7 @@ contract L1WETHGateway is L1ERC20Gateway {
|
||||
address _router,
|
||||
address _messenger
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,35 +49,15 @@ contract L1USDCGateway is L1ERC20Gateway, IUSDCBurnableSourceBridge {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1USDCGateway` implementation contract.
|
||||
///
|
||||
/// @param _l1USDC The address of USDC in L1.
|
||||
/// @param _l2USDC The address of USDC in L2.
|
||||
/// @param _counterpart The address of `L2USDCGateway` contract in L2.
|
||||
/// @param _router The address of `L1GatewayRouter` contract.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(
|
||||
address _l1USDC,
|
||||
address _l2USDC,
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_l1USDC == address(0) || _l2USDC == address(0) || _router == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
|
||||
constructor(address _l1USDC, address _l2USDC) {
|
||||
_disableInitializers();
|
||||
|
||||
l1USDC = _l1USDC;
|
||||
l2USDC = _l2USDC;
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1USDCGateway.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L2USDCGateway in L2.
|
||||
/// @notice Initialize the storage of L1WETHGateway.
|
||||
/// @param _counterpart The address of L2ETHGateway in L2.
|
||||
/// @param _router The address of L1GatewayRouter.
|
||||
/// @param _messenger The address of L1ScrollMessenger.
|
||||
function initialize(
|
||||
@@ -85,6 +65,7 @@ contract L1USDCGateway is L1ERC20Gateway, IUSDCBurnableSourceBridge {
|
||||
address _router,
|
||||
address _messenger
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,20 +24,12 @@ contract L1USDCGatewayCCTP is CCTPGatewayBase, L1ERC20Gateway {
|
||||
constructor(
|
||||
address _l1USDC,
|
||||
address _l2USDC,
|
||||
uint32 _destinationDomain,
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) CCTPGatewayBase(_l1USDC, _l2USDC, _destinationDomain) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_router == address(0)) revert ErrorZeroAddress();
|
||||
|
||||
uint32 _destinationDomain
|
||||
) CCTPGatewayBase(_l1USDC, _l2USDC, _destinationDomain) {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1USDCGatewayCCTP.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router`, `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L2USDCGatewayCCTP in L2.
|
||||
/// @param _router The address of L1GatewayRouter.
|
||||
/// @param _messenger The address of L1ScrollMessenger.
|
||||
@@ -50,6 +42,7 @@ contract L1USDCGatewayCCTP is CCTPGatewayBase, L1ERC20Gateway {
|
||||
address _cctpMessenger,
|
||||
address _cctpTransmitter
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
CCTPGatewayBase._initialize(_cctpMessenger, _cctpTransmitter);
|
||||
}
|
||||
|
||||
@@ -33,23 +33,6 @@ interface IL1MessageQueue {
|
||||
/// @param index The index of message dropped.
|
||||
event DropTransaction(uint256 index);
|
||||
|
||||
/// @notice Emitted when owner updates gas oracle contract.
|
||||
/// @param _oldGasOracle The address of old gas oracle contract.
|
||||
/// @param _newGasOracle The address of new gas oracle contract.
|
||||
event UpdateGasOracle(address indexed _oldGasOracle, address indexed _newGasOracle);
|
||||
|
||||
/// @notice Emitted when owner updates max gas limit.
|
||||
/// @param _oldMaxGasLimit The old max gas limit.
|
||||
/// @param _newMaxGasLimit The new max gas limit.
|
||||
event UpdateMaxGasLimit(uint256 _oldMaxGasLimit, uint256 _newMaxGasLimit);
|
||||
|
||||
/**********
|
||||
* Errors *
|
||||
**********/
|
||||
|
||||
/// @dev Thrown when the given address is `address(0)`.
|
||||
error ErrorZeroAddress();
|
||||
|
||||
/*************************
|
||||
* Public View Functions *
|
||||
*************************/
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.16;
|
||||
|
||||
import {IL1MessageQueue} from "./IL1MessageQueue.sol";
|
||||
|
||||
interface IL1MessageQueueWithGasPriceOracle is IL1MessageQueue {
|
||||
/**********
|
||||
* Events *
|
||||
**********/
|
||||
|
||||
/// @notice Emitted when owner updates whitelist checker contract.
|
||||
/// @param _oldWhitelistChecker The address of old whitelist checker contract.
|
||||
/// @param _newWhitelistChecker The address of new whitelist checker contract.
|
||||
event UpdateWhitelistChecker(address indexed _oldWhitelistChecker, address indexed _newWhitelistChecker);
|
||||
|
||||
/// @notice Emitted when current l2 base fee is updated.
|
||||
/// @param oldL2BaseFee The original l2 base fee before update.
|
||||
/// @param newL2BaseFee The current l2 base fee updated.
|
||||
event UpdateL2BaseFee(uint256 oldL2BaseFee, uint256 newL2BaseFee);
|
||||
|
||||
/**********
|
||||
* Errors *
|
||||
**********/
|
||||
|
||||
/// @dev Thrown when the caller is not whitelisted.
|
||||
error ErrorNotWhitelistedSender();
|
||||
}
|
||||
@@ -3,11 +3,6 @@
|
||||
pragma solidity ^0.8.16;
|
||||
|
||||
interface IL2GasPriceOracle {
|
||||
/// @notice The latest known l2 base fee.
|
||||
function l2BaseFee() external view returns (uint256);
|
||||
|
||||
function whitelist() external view returns (address);
|
||||
|
||||
/// @notice Estimate fee for cross chain message call.
|
||||
/// @param _gasLimit Gas limit required to complete the message relay on L2.
|
||||
function estimateCrossDomainMessageFee(uint256 _gasLimit) external view returns (uint256);
|
||||
|
||||
@@ -24,13 +24,6 @@ interface IScrollChain {
|
||||
/// @param withdrawRoot The merkle root on layer2 after this batch.
|
||||
event FinalizeBatch(uint256 indexed batchIndex, bytes32 indexed batchHash, bytes32 stateRoot, bytes32 withdrawRoot);
|
||||
|
||||
/**********
|
||||
* Errors *
|
||||
**********/
|
||||
|
||||
/// @dev Thrown when the given address is `address(0)`.
|
||||
error ErrorZeroAddress();
|
||||
|
||||
/*************************
|
||||
* Public View Functions *
|
||||
*************************/
|
||||
|
||||
@@ -20,31 +20,37 @@ import {AddressAliasHelper} from "../../libraries/common/AddressAliasHelper.sol"
|
||||
contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
using BitMapsUpgradeable for BitMapsUpgradeable.BitMap;
|
||||
|
||||
/*************
|
||||
* Constants *
|
||||
*************/
|
||||
/**********
|
||||
* Events *
|
||||
**********/
|
||||
|
||||
/// @notice The address of L1ScrollMessenger contract.
|
||||
address public immutable messenger;
|
||||
/// @notice Emitted when owner updates gas oracle contract.
|
||||
/// @param _oldGasOracle The address of old gas oracle contract.
|
||||
/// @param _newGasOracle The address of new gas oracle contract.
|
||||
event UpdateGasOracle(address indexed _oldGasOracle, address indexed _newGasOracle);
|
||||
|
||||
/// @notice The address of ScrollChain contract.
|
||||
address public immutable scrollChain;
|
||||
/// @notice Emitted when owner updates EnforcedTxGateway contract.
|
||||
/// @param _oldGateway The address of old EnforcedTxGateway contract.
|
||||
/// @param _newGateway The address of new EnforcedTxGateway contract.
|
||||
event UpdateEnforcedTxGateway(address indexed _oldGateway, address indexed _newGateway);
|
||||
|
||||
/// @notice The address EnforcedTxGateway contract.
|
||||
address public immutable enforcedTxGateway;
|
||||
/// @notice Emitted when owner updates max gas limit.
|
||||
/// @param _oldMaxGasLimit The old max gas limit.
|
||||
/// @param _newMaxGasLimit The new max gas limit.
|
||||
event UpdateMaxGasLimit(uint256 _oldMaxGasLimit, uint256 _newMaxGasLimit);
|
||||
|
||||
/*************
|
||||
* Variables *
|
||||
*************/
|
||||
|
||||
/// @dev The storage slot used as L1ScrollMessenger contract, which is deprecated now.
|
||||
address private __messenger;
|
||||
/// @notice The address of L1ScrollMessenger contract.
|
||||
address public messenger;
|
||||
|
||||
/// @dev The storage slot used as ScrollChain contract, which is deprecated now.
|
||||
address private __scrollChain;
|
||||
/// @notice The address of ScrollChain contract.
|
||||
address public scrollChain;
|
||||
|
||||
/// @dev The storage slot used as EnforcedTxGateway contract, which is deprecated now.
|
||||
address private __enforcedTxGateway;
|
||||
/// @notice The address EnforcedTxGateway contract.
|
||||
address public enforcedTxGateway;
|
||||
|
||||
/// @notice The address of GasOracle contract.
|
||||
address public gasOracle;
|
||||
@@ -64,9 +70,6 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
/// @dev The bitmap for skipped messages, where `skippedMessageBitmap[i]` keeps the bits from `[i*256, (i+1)*256)`.
|
||||
mapping(uint256 => uint256) private skippedMessageBitmap;
|
||||
|
||||
/// @dev The storage slots for future usage.
|
||||
uint256[41] private __gap;
|
||||
|
||||
/**********************
|
||||
* Function Modifiers *
|
||||
**********************/
|
||||
@@ -80,36 +83,10 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1MessageQueue` implementation contract.
|
||||
///
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
/// @param _scrollChain The address of `ScrollChain` contract.
|
||||
/// @param _enforcedTxGateway The address of `EnforcedTxGateway` contract.
|
||||
constructor(
|
||||
address _messenger,
|
||||
address _scrollChain,
|
||||
address _enforcedTxGateway
|
||||
) {
|
||||
if (_messenger == address(0) || _scrollChain == address(0) || _enforcedTxGateway == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
|
||||
messenger = _messenger;
|
||||
scrollChain = _scrollChain;
|
||||
enforcedTxGateway = _enforcedTxGateway;
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L1MessageQueue.
|
||||
///
|
||||
/// @dev The parameters `_messenger`, `_scrollChain` and `_enforcedTxGateway` are no longer used.
|
||||
///
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
/// @param _scrollChain The address of `ScrollChain` contract.
|
||||
/// @param _enforcedTxGateway The address of `EnforcedTxGateway` contract.
|
||||
/// @param _gasOracle The address of `GasOracle` contract.
|
||||
/// @param _maxGasLimit The maximum gas limit allowed in single transaction.
|
||||
function initialize(
|
||||
address _messenger,
|
||||
address _scrollChain,
|
||||
@@ -118,12 +95,12 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
uint256 _maxGasLimit
|
||||
) external initializer {
|
||||
OwnableUpgradeable.__Ownable_init();
|
||||
|
||||
messenger = _messenger;
|
||||
scrollChain = _scrollChain;
|
||||
enforcedTxGateway = _enforcedTxGateway;
|
||||
gasOracle = _gasOracle;
|
||||
maxGasLimit = _maxGasLimit;
|
||||
|
||||
__messenger = _messenger;
|
||||
__scrollChain = _scrollChain;
|
||||
__enforcedTxGateway = _enforcedTxGateway;
|
||||
}
|
||||
|
||||
/*************************
|
||||
@@ -141,14 +118,14 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
}
|
||||
|
||||
/// @inheritdoc IL1MessageQueue
|
||||
function estimateCrossDomainMessageFee(uint256 _gasLimit) external view virtual override returns (uint256) {
|
||||
function estimateCrossDomainMessageFee(uint256 _gasLimit) external view override returns (uint256) {
|
||||
address _oracle = gasOracle;
|
||||
if (_oracle == address(0)) return 0;
|
||||
return IL2GasPriceOracle(_oracle).estimateCrossDomainMessageFee(_gasLimit);
|
||||
}
|
||||
|
||||
/// @inheritdoc IL1MessageQueue
|
||||
function calculateIntrinsicGasFee(bytes calldata _calldata) public view virtual override returns (uint256) {
|
||||
function calculateIntrinsicGasFee(bytes memory _calldata) public view override returns (uint256) {
|
||||
address _oracle = gasOracle;
|
||||
if (_oracle == address(0)) return 0;
|
||||
return IL2GasPriceOracle(_oracle).calculateIntrinsicGasFee(_calldata);
|
||||
@@ -392,6 +369,16 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
emit UpdateGasOracle(_oldGasOracle, _newGasOracle);
|
||||
}
|
||||
|
||||
/// @notice Update the address of EnforcedTxGateway.
|
||||
/// @dev This function can only called by contract owner.
|
||||
/// @param _newGateway The address to update.
|
||||
function updateEnforcedTxGateway(address _newGateway) external onlyOwner {
|
||||
address _oldGateway = enforcedTxGateway;
|
||||
enforcedTxGateway = _newGateway;
|
||||
|
||||
emit UpdateEnforcedTxGateway(_oldGateway, _newGateway);
|
||||
}
|
||||
|
||||
/// @notice Update the max gas limit.
|
||||
/// @dev This function can only called by contract owner.
|
||||
/// @param _newMaxGasLimit The new max gas limit.
|
||||
@@ -428,7 +415,7 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
|
||||
emit QueueTransaction(_sender, _target, _value, uint64(_queueIndex), _gasLimit, _data);
|
||||
}
|
||||
|
||||
function _validateGasLimit(uint256 _gasLimit, bytes calldata _calldata) internal view {
|
||||
function _validateGasLimit(uint256 _gasLimit, bytes memory _calldata) internal view {
|
||||
require(_gasLimit <= maxGasLimit, "Gas limit must not exceed maxGasLimit");
|
||||
// check if the gas limit is above intrinsic gas
|
||||
uint256 intrinsicGas = calculateIntrinsicGasFee(_calldata);
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
import {IWhitelist} from "../../libraries/common/IWhitelist.sol";
|
||||
import {IL1MessageQueue} from "./IL1MessageQueue.sol";
|
||||
import {IL1MessageQueueWithGasPriceOracle} from "./IL1MessageQueueWithGasPriceOracle.sol";
|
||||
import {IL2GasPriceOracle} from "./IL2GasPriceOracle.sol";
|
||||
|
||||
import {L1MessageQueue} from "./L1MessageQueue.sol";
|
||||
|
||||
contract L1MessageQueueWithGasPriceOracle is L1MessageQueue, IL1MessageQueueWithGasPriceOracle {
|
||||
/*************
|
||||
* Constants *
|
||||
*************/
|
||||
|
||||
/// @notice The intrinsic gas for transaction.
|
||||
uint256 private constant INTRINSIC_GAS_TX = 21000;
|
||||
|
||||
/// @notice The intrinsic gas for each nonzero byte.
|
||||
uint256 private constant INTRINSIC_GAS_NONZERO_BYTE = 16;
|
||||
|
||||
/*************
|
||||
* Variables *
|
||||
*************/
|
||||
|
||||
/// @notice The latest known l2 base fee.
|
||||
uint256 public l2BaseFee;
|
||||
|
||||
/// @notice The address of whitelist checker contract.
|
||||
address public whitelistChecker;
|
||||
|
||||
/***************
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L1MessageQueueWithGasPriceOracle` implementation contract.
|
||||
///
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
/// @param _scrollChain The address of `ScrollChain` contract.
|
||||
/// @param _enforcedTxGateway The address of `EnforcedTxGateway` contract.
|
||||
constructor(
|
||||
address _messenger,
|
||||
address _scrollChain,
|
||||
address _enforcedTxGateway
|
||||
) L1MessageQueue(_messenger, _scrollChain, _enforcedTxGateway) {}
|
||||
|
||||
/// @notice Initialize the storage of L1MessageQueueWithGasPriceOracle.
|
||||
function initializeV2() external reinitializer(2) {
|
||||
l2BaseFee = IL2GasPriceOracle(gasOracle).l2BaseFee();
|
||||
whitelistChecker = IL2GasPriceOracle(gasOracle).whitelist();
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Public View Functions *
|
||||
*************************/
|
||||
|
||||
/// @inheritdoc IL1MessageQueue
|
||||
function estimateCrossDomainMessageFee(uint256 _gasLimit)
|
||||
external
|
||||
view
|
||||
override(IL1MessageQueue, L1MessageQueue)
|
||||
returns (uint256)
|
||||
{
|
||||
return _gasLimit * l2BaseFee;
|
||||
}
|
||||
|
||||
/// @inheritdoc IL1MessageQueue
|
||||
function calculateIntrinsicGasFee(bytes calldata _calldata)
|
||||
public
|
||||
pure
|
||||
override(IL1MessageQueue, L1MessageQueue)
|
||||
returns (uint256)
|
||||
{
|
||||
// no way this can overflow `uint256`
|
||||
unchecked {
|
||||
return INTRINSIC_GAS_TX + _calldata.length * INTRINSIC_GAS_NONZERO_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* Public Mutating Functions *
|
||||
*****************************/
|
||||
|
||||
/// @notice Allows whitelistCheckered caller to modify the l2 base fee.
|
||||
/// @param _newL2BaseFee The new l2 base fee.
|
||||
function setL2BaseFee(uint256 _newL2BaseFee) external {
|
||||
if (!IWhitelist(whitelistChecker).isSenderAllowed(_msgSender())) {
|
||||
revert ErrorNotWhitelistedSender();
|
||||
}
|
||||
|
||||
uint256 _oldL2BaseFee = l2BaseFee;
|
||||
l2BaseFee = _newL2BaseFee;
|
||||
|
||||
emit UpdateL2BaseFee(_oldL2BaseFee, _newL2BaseFee);
|
||||
}
|
||||
|
||||
/************************
|
||||
* Restricted Functions *
|
||||
************************/
|
||||
|
||||
/// @notice Update whitelist checker contract.
|
||||
/// @dev This function can only called by contract owner.
|
||||
/// @param _newWhitelistChecker The address of new whitelist checker contract.
|
||||
function updateWhitelistChecker(address _newWhitelistChecker) external onlyOwner {
|
||||
address _oldWhitelistChecker = whitelistChecker;
|
||||
whitelistChecker = _newWhitelistChecker;
|
||||
emit UpdateWhitelistChecker(_oldWhitelistChecker, _newWhitelistChecker);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ contract L2GasPriceOracle is OwnableUpgradeable, IL2GasPriceOracle {
|
||||
uint256 public l2BaseFee;
|
||||
|
||||
/// @notice The address of whitelist contract.
|
||||
address public whitelist;
|
||||
IWhitelist public whitelist;
|
||||
|
||||
struct IntrinsicParams {
|
||||
// The intrinsic gas for transaction.
|
||||
@@ -111,7 +111,7 @@ contract L2GasPriceOracle is OwnableUpgradeable, IL2GasPriceOracle {
|
||||
/// @notice Allows whitelisted caller to modify the l2 base fee.
|
||||
/// @param _newL2BaseFee The new l2 base fee.
|
||||
function setL2BaseFee(uint256 _newL2BaseFee) external {
|
||||
require(IWhitelist(whitelist).isSenderAllowed(_msgSender()), "Not whitelisted sender");
|
||||
require(whitelist.isSenderAllowed(_msgSender()), "Not whitelisted sender");
|
||||
|
||||
uint256 _oldL2BaseFee = l2BaseFee;
|
||||
l2BaseFee = _newL2BaseFee;
|
||||
@@ -127,9 +127,9 @@ contract L2GasPriceOracle is OwnableUpgradeable, IL2GasPriceOracle {
|
||||
/// @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;
|
||||
address _oldWhitelist = address(whitelist);
|
||||
|
||||
whitelist = _newWhitelist;
|
||||
whitelist = IWhitelist(_newWhitelist);
|
||||
emit UpdateWhitelist(_oldWhitelist, _newWhitelist);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
|
||||
/// @param status The status of the account updated.
|
||||
event UpdateProver(address indexed account, bool status);
|
||||
|
||||
/// @notice Emitted when the address of rollup verifier is updated.
|
||||
/// @param oldVerifier The address of old rollup verifier.
|
||||
/// @param newVerifier The address of new rollup verifier.
|
||||
event UpdateVerifier(address indexed oldVerifier, address indexed newVerifier);
|
||||
|
||||
/// @notice Emitted when the value of `maxNumTxInChunk` is updated.
|
||||
/// @param oldMaxNumTxInChunk The old value of `maxNumTxInChunk`.
|
||||
/// @param newMaxNumTxInChunk The new value of `maxNumTxInChunk`.
|
||||
@@ -43,12 +48,6 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
|
||||
/// @notice The chain id of the corresponding layer 2 chain.
|
||||
uint64 public immutable layer2ChainId;
|
||||
|
||||
/// @notice The address of L1MessageQueue contract.
|
||||
address public immutable messageQueue;
|
||||
|
||||
/// @notice The address of RollupVerifier.
|
||||
address public immutable verifier;
|
||||
|
||||
/*************
|
||||
* Variables *
|
||||
*************/
|
||||
@@ -56,11 +55,11 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
|
||||
/// @notice The maximum number of transactions allowed in each chunk.
|
||||
uint256 public maxNumTxInChunk;
|
||||
|
||||
/// @dev The storage slot used as L1MessageQueue contract, which is deprecated now.
|
||||
address private __messageQueue;
|
||||
/// @notice The address of L1MessageQueue.
|
||||
address public messageQueue;
|
||||
|
||||
/// @dev The storage slot used as RollupVerifier contract, which is deprecated now.
|
||||
address private __verifier;
|
||||
/// @notice The address of RollupVerifier.
|
||||
address public verifier;
|
||||
|
||||
/// @notice Whether an account is a sequencer.
|
||||
mapping(address => bool) public isSequencer;
|
||||
@@ -99,34 +98,12 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `ScrollChain` implementation contract.
|
||||
///
|
||||
/// @param _chainId The chain id of L2.
|
||||
/// @param _messageQueue The address of `L1MessageQueue` contract.
|
||||
/// @param _verifier The address of zkevm verifier contract.
|
||||
constructor(
|
||||
uint64 _chainId,
|
||||
address _messageQueue,
|
||||
address _verifier
|
||||
) {
|
||||
if (_messageQueue == address(0) || _verifier == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
|
||||
constructor(uint64 _chainId) {
|
||||
_disableInitializers();
|
||||
|
||||
layer2ChainId = _chainId;
|
||||
messageQueue = _messageQueue;
|
||||
verifier = _verifier;
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of ScrollChain.
|
||||
///
|
||||
/// @dev The parameters `_messageQueue` are no longer used.
|
||||
///
|
||||
/// @param _messageQueue The address of `L1MessageQueue` contract.
|
||||
/// @param _verifier The address of zkevm verifier contract.
|
||||
/// @param _maxNumTxInChunk The maximum number of transactions allowed in each chunk.
|
||||
function initialize(
|
||||
address _messageQueue,
|
||||
address _verifier,
|
||||
@@ -134,10 +111,11 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
|
||||
) public initializer {
|
||||
OwnableUpgradeable.__Ownable_init();
|
||||
|
||||
messageQueue = _messageQueue;
|
||||
verifier = _verifier;
|
||||
maxNumTxInChunk = _maxNumTxInChunk;
|
||||
__verifier = _verifier;
|
||||
__messageQueue = _messageQueue;
|
||||
|
||||
emit UpdateVerifier(address(0), _verifier);
|
||||
emit UpdateMaxNumTxInChunk(0, _maxNumTxInChunk);
|
||||
}
|
||||
|
||||
@@ -418,6 +396,15 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
|
||||
emit UpdateProver(_account, false);
|
||||
}
|
||||
|
||||
/// @notice Update the address verifier contract.
|
||||
/// @param _newVerifier The address of new verifier contract.
|
||||
function updateVerifier(address _newVerifier) external onlyOwner {
|
||||
address _oldVerifier = verifier;
|
||||
verifier = _newVerifier;
|
||||
|
||||
emit UpdateVerifier(_oldVerifier, _newVerifier);
|
||||
}
|
||||
|
||||
/// @notice Update the value of `maxNumTxInChunk`.
|
||||
/// @param _maxNumTxInChunk The new value of `maxNumTxInChunk`.
|
||||
function updateMaxNumTxInChunk(uint256 _maxNumTxInChunk) external onlyOwner {
|
||||
|
||||
@@ -48,18 +48,17 @@ contract L2ScrollMessenger is ScrollMessengerBase, IL2ScrollMessenger {
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
constructor(address _counterpart, address _messageQueue) ScrollMessengerBase(_counterpart) {
|
||||
if (_messageQueue == address(0)) {
|
||||
revert ErrorZeroAddress();
|
||||
}
|
||||
constructor(address _messageQueue) {
|
||||
if (_messageQueue == address(0)) revert ErrZeroAddress();
|
||||
|
||||
_disableInitializers();
|
||||
|
||||
messageQueue = _messageQueue;
|
||||
}
|
||||
|
||||
function initialize(address) external initializer {
|
||||
ScrollMessengerBase.__ScrollMessengerBase_init(address(0), address(0));
|
||||
function initialize(address _counterpart) external initializer {
|
||||
if (_counterpart == address(0)) revert ErrZeroAddress();
|
||||
ScrollMessengerBase.__ScrollMessengerBase_init(_counterpart, address(0));
|
||||
}
|
||||
|
||||
/*****************************
|
||||
|
||||
@@ -35,34 +35,17 @@ contract L2CustomERC20Gateway is L2ERC20Gateway {
|
||||
/***************
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L2CustomERC20Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L1CustomERC20Gateway` contract in L1.
|
||||
/// @param _router The address of `L2GatewayRouter` contract in L2.
|
||||
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
|
||||
constructor(
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_router == address(0)) revert ErrorZeroAddress();
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of `L2CustomERC20Gateway`.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of `L1CustomERC20Gateway` contract in L1.
|
||||
/// @param _router The address of `L2GatewayRouter` contract in L2.
|
||||
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
|
||||
function initialize(
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
}
|
||||
|
||||
|
||||
11
contracts/src/L2/gateways/L2DAIGateway.sol
Normal file
11
contracts/src/L2/gateways/L2DAIGateway.sol
Normal file
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity =0.8.16;
|
||||
|
||||
import {L2CustomERC20Gateway} from "./L2CustomERC20Gateway.sol";
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
|
||||
contract L2DAIGateway is L2CustomERC20Gateway {
|
||||
|
||||
}
|
||||
@@ -39,21 +39,10 @@ contract L2ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL2ERC
|
||||
/***************
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L2ERC1155Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L1ERC1155Gateway` contract in L1.
|
||||
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
|
||||
constructor(address _counterpart, address _messenger) ScrollGatewayBase(_counterpart, address(0), _messenger) {
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of `L2ERC1155Gateway`.
|
||||
///
|
||||
/// @dev The parameters `_counterpart` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of `L1ERC1155Gateway` contract in L1.
|
||||
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
|
||||
function initialize(address _counterpart, address _messenger) external initializer {
|
||||
ERC1155HolderUpgradeable.__ERC1155Holder_init();
|
||||
ERC1155ReceiverUpgradeable.__ERC1155Receiver_init();
|
||||
|
||||
@@ -39,21 +39,10 @@ contract L2ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL2ERC72
|
||||
/***************
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L2ERC721Gateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L1ERC721Gateway` contract in L1.
|
||||
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
|
||||
constructor(address _counterpart, address _messenger) ScrollGatewayBase(_counterpart, address(0), _messenger) {
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of `L2ERC721Gateway`.
|
||||
///
|
||||
/// @dev The parameters `_counterpart` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of `L1ERC721Gateway` contract in L1.
|
||||
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
|
||||
function initialize(address _counterpart, address _messenger) external initializer {
|
||||
ERC721HolderUpgradeable.__ERC721Holder_init();
|
||||
|
||||
|
||||
@@ -17,27 +17,12 @@ contract L2ETHGateway is ScrollGatewayBase, IL2ETHGateway {
|
||||
/***************
|
||||
* Constructor *
|
||||
***************/
|
||||
|
||||
/// @notice Constructor for `L2ETHGateway` implementation contract.
|
||||
///
|
||||
/// @param _counterpart The address of `L1ETHGateway` contract in L1.
|
||||
/// @param _router The address of `L1GatewayRouter` contract.
|
||||
/// @param _messenger The address of `L1ScrollMessenger` contract.
|
||||
constructor(
|
||||
address _counterpart,
|
||||
address _router,
|
||||
address _messenger
|
||||
) ScrollGatewayBase(_counterpart, _router, _messenger) {
|
||||
if (_router == address(0)) revert ErrorZeroAddress();
|
||||
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
|
||||
/// @notice Initialize the storage of L2ETHGateway.
|
||||
///
|
||||
/// @dev The parameters `_counterpart`, `_router` and `_messenger` are no longer used.
|
||||
///
|
||||
/// @param _counterpart The address of L1ETHGateway in L1.
|
||||
/// @param _counterpart The address of L1ETHGateway in L2.
|
||||
/// @param _router The address of L2GatewayRouter.
|
||||
/// @param _messenger The address of L2ScrollMessenger.
|
||||
function initialize(
|
||||
@@ -45,6 +30,7 @@ contract L2ETHGateway is ScrollGatewayBase, IL2ETHGateway {
|
||||
address _router,
|
||||
address _messenger
|
||||
) external initializer {
|
||||
require(_router != address(0), "zero router address");
|
||||
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
|
||||
}
|
||||
|
||||
@@ -108,12 +94,9 @@ contract L2ETHGateway is ScrollGatewayBase, IL2ETHGateway {
|
||||
|
||||
// 1. Extract real sender if this call is from L1GatewayRouter.
|
||||
address _from = _msgSender();
|
||||
|
||||
/* comment out since router won't use this contract anymore
|
||||
if (router == _from) {
|
||||
(_from, _data) = abi.decode(_data, (address, bytes));
|
||||
}
|
||||
*/
|
||||
|
||||
// @note no rate limit here, since ETH is limited in messenger
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user