Compare commits

..

41 Commits

Author SHA1 Message Date
HAOYUatHZ
9f1262e141 stash 2023-08-05 10:47:54 +08:00
HAOYUatHZ
b88abbf45d some renamings 2023-08-05 10:36:16 +08:00
HAOYUatHZ
11e560fb7c move 2023-08-05 10:35:01 +08:00
colinlyguo
b42a17580b go mod tidy and bump version 2023-08-05 03:41:04 +08:00
colinlyguo
47bf98eb30 address comments 2023-08-05 03:32:29 +08:00
colinlyguo
e3a49fc041 happy path integration test 2023-08-04 22:31:56 +08:00
colinlyguo
72355067b8 fix get task and proof 2023-08-04 20:56:52 +08:00
georgehao
fcf34edbfb feat(coordinator): add prover rest api (#716)
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
2023-08-04 20:48:17 +08:00
georgehao
d11de12637 Merge branch 'develop' of github.com:scroll-tech/scroll into pull-model-prover-client 2023-08-04 17:01:31 +08:00
colin
3be3f9926a Merge branch 'develop' into pull-model-prover-client 2023-08-04 15:22:39 +08:00
colin
ba51b5794d Merge branch 'develop' into pull-model-prover-client 2023-08-04 14:37:08 +08:00
colinlyguo
f22efbff22 tweak integration-test 2023-08-03 20:02:26 +08:00
colin
8f92ca9010 Merge branch 'develop' into pull-model-prover-client 2023-08-03 19:33:16 +08:00
colinlyguo
2c69352948 fix 2023-08-03 19:17:22 +08:00
colinlyguo
0652852c16 address comments 2023-08-03 19:01:46 +08:00
colinlyguo
bbb4ca6d76 revert flag change 2023-08-03 17:56:26 +08:00
colinlyguo
1b542830af add mock_proof_submission config 2023-08-03 17:38:25 +08:00
colinlyguo
975e61afe4 tweak 2023-08-03 17:12:45 +08:00
colinlyguo
7bf538f287 refactor error code 2023-08-03 17:08:26 +08:00
colinlyguo
58fc8a3add remove signature 2023-08-03 16:30:27 +08:00
colinlyguo
bf9dabd9b7 tweak login request 2023-08-03 15:54:50 +08:00
colinlyguo
beea5754cb add retry mechanism for JWT expiration 2023-08-03 15:46:14 +08:00
colin
d0c82f78ad Merge branch 'develop' into pull-model-prover-client 2023-08-03 15:03:02 +08:00
colinlyguo
3913a7397c run goimport 2023-08-03 15:01:51 +08:00
colinlyguo
c63e25a9bf add login auth 2023-08-03 14:57:24 +08:00
colinlyguo
8960849677 address comments 2023-08-03 13:39:31 +08:00
colinlyguo
24d8658ddb address comments 2023-08-03 13:11:12 +08:00
colinlyguo
f88f883b6a simplify http body result marshal 2023-08-03 11:46:57 +08:00
colinlyguo
c8fd76dd02 trigger ci 2023-08-02 16:48:04 +08:00
colin
b82bbedaca Merge branch 'develop' into pull-model-prover-client 2023-08-02 16:36:14 +08:00
colinlyguo
1ea0dcd0ae bump version 2023-08-02 16:35:42 +08:00
colinlyguo
e87bdbabe2 tweak code 2023-08-02 16:32:41 +08:00
colinlyguo
4db1565ba3 comment out prover start process test (coordinator not support login yet) 2023-08-02 03:13:36 +08:00
colinlyguo
2425374362 fix 2023-08-02 03:05:06 +08:00
colinlyguo
89b2e3133a scrollfmt 2023-08-02 02:44:42 +08:00
colinlyguo
5b7a2bb40c bump version 2023-08-02 02:36:18 +08:00
colinlyguo
0466e2d201 add retry configs 2023-08-02 02:32:05 +08:00
colinlyguo
f86cbb2bcb fix 2023-08-02 02:14:30 +08:00
colin
712c2c5ad3 Merge branch 'develop' into pull-model-prover-client 2023-08-02 01:54:47 +08:00
colinlyguo
a8a5db9a18 fix 2023-08-01 22:27:45 +08:00
colinlyguo
61d8b48b73 a commit 2023-08-01 21:05:13 +08:00
148 changed files with 1299 additions and 2851 deletions

View File

@@ -43,8 +43,6 @@ jobs:
version: '0.8.16'
- name: Install Geth Tools
uses: gacts/install-geth-tools@v1
with:
version: 1.10.19
- name: Lint
working-directory: 'bridge'
run: |
@@ -94,8 +92,6 @@ jobs:
version: '0.8.16'
- name: Install Geth Tools
uses: gacts/install-geth-tools@v1
with:
version: 1.10.19
- name: Build prerequisites
run: |
make dev_docker

View File

@@ -88,8 +88,6 @@ jobs:
version: '0.8.16'
- name: Install Geth Tools
uses: gacts/install-geth-tools@v1
with:
version: 1.10.19
- name: Build prerequisites
run: |
make dev_docker

View File

@@ -104,8 +104,6 @@ jobs:
version: '0.8.16'
- name: Install Geth Tools
uses: gacts/install-geth-tools@v1
with:
version: 1.10.19
- name: Build prerequisites
run: |
make dev_docker

View File

@@ -81,8 +81,6 @@ jobs:
version: '0.8.16'
- name: Install Geth Tools
uses: gacts/install-geth-tools@v1
with:
version: 1.10.19
- name: Build prerequisites
run: |
make dev_docker

View File

@@ -6,7 +6,7 @@ on:
- v**
jobs:
event_watcher:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
@@ -27,18 +27,6 @@ jobs:
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:
@@ -48,18 +36,6 @@ jobs:
tags: scrolltech/gas-oracle:${{github.ref_name}}
# cache-from: type=gha,scope=${{ github.workflow }}
# cache-to: type=gha,scope=${{ github.workflow }}
msg_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 msg_relayer docker
uses: docker/build-push-action@v2
with:
@@ -69,18 +45,6 @@ jobs:
tags: scrolltech/msg-relayer:${{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:
@@ -90,18 +54,6 @@ jobs:
tags: scrolltech/rollup-relayer:${{github.ref_name}}
# cache-from: type=gha,scope=${{ github.workflow }}
# cache-to: type=gha,scope=${{ github.workflow }}
bridgehistoryapi-cross-msg-fetcher:
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 bridgehistoryapi-cross-msg-fetcher docker
uses: docker/build-push-action@v2
with:
@@ -111,18 +63,6 @@ jobs:
tags: scrolltech/bridgehistoryapi-cross-msg-fetcher:${{github.ref_name}}
# cache-from: type=gha,scope=${{ github.workflow }}
# cache-to: type=gha,scope=${{ github.workflow }}
bridgehistoryapi-server:
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 bridgehistoryapi-server docker
uses: docker/build-push-action@v2
with:
@@ -132,18 +72,6 @@ jobs:
tags: scrolltech/bridgehistoryapi-server:${{github.ref_name}}
# cache-from: type=gha,scope=${{ github.workflow }}
# cache-to: type=gha,scope=${{ github.workflow }}
coordinator:
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:
@@ -153,24 +81,3 @@ jobs:
tags: scrolltech/coordinator:${{github.ref_name}}
# cache-from: type=gha,scope=${{ github.workflow }}
# cache-to: type=gha,scope=${{ github.workflow }}
prover-stats-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 prover-stats-api docker
uses: docker/build-push-action@v2
with:
context: .
file: ./build/dockerfiles/prover-stats-api.Dockerfile
push: true
tags: scrolltech/prover-stats-api:${{github.ref_name}}
# cache-from: type=gha,scope=${{ github.workflow }}
# cache-to: type=gha,scope=${{ github.workflow }}

View File

@@ -33,8 +33,6 @@ jobs:
version: '0.8.16'
- name: Install Geth Tools
uses: gacts/install-geth-tools@v1
with:
version: 1.10.19
- name: Build prerequisites
run: |
make dev_docker

File diff suppressed because one or more lines are too long

View File

@@ -53,11 +53,11 @@ func (m *MsgProofUpdater) Start() {
continue
}
latestBatchIndexWithProof, err := m.l2SentMsgOrm.GetLatestL2SentMsgBatchIndex(m.ctx)
log.Info("latest batc with proof", "batch_index", latestBatchIndexWithProof)
if err != nil {
log.Error("MsgProofUpdater: Can not get latest L2SentMsgBatchIndex: ", "err", err)
continue
}
log.Info("latest batch with proof", "batch_index", latestBatchIndexWithProof)
var start uint64
if latestBatchIndexWithProof < 0 {
start = 1

View File

@@ -15,7 +15,6 @@ func Route(router *gin.Engine, conf *config.Config) {
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))

View File

@@ -204,7 +204,7 @@ func (c *CrossMsg) DeleteL1CrossMsgAfterHeight(ctx context.Context, height uint6
// GetL2CrossMsgByHash returns layer2 cross message by given hash
func (c *CrossMsg) GetL2CrossMsgByHash(ctx context.Context, l2Hash common.Hash) (*CrossMsg, error) {
var result CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).Where("layer2_hash = ? AND msg_type = ?", l2Hash.String(), Layer2Msg).First(&result).Error
err := c.db.WithContext(ctx).Model(&CrossMsg{}).Where("layer2_hash = ? AND msg_type = ?", l2Hash.String(), Layer1Msg).First(&result).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil

View File

@@ -2,7 +2,6 @@ package orm
import (
"context"
"errors"
"fmt"
"time"
@@ -103,9 +102,6 @@ func (l *L2SentMsg) GetLatestL2SentMsgBatchIndex(ctx context.Context) (int64, er
Select("batch_index").
First(&result).
Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return -1, nil
}
if err != nil {
return -1, fmt.Errorf("L2SentMsg.GetLatestL2SentMsgBatchIndex error: %w", err)
}

View File

@@ -1,6 +1,7 @@
package utils
import (
"bytes"
"context"
"encoding/binary"
"errors"
@@ -75,14 +76,6 @@ func GetBatchRangeFromCalldataV2(calldata []byte) (uint64, uint64, uint64, error
method := backendabi.ScrollChainV2ABI.Methods["commitBatch"]
values, err := method.Inputs.Unpack(calldata[4:])
if err != nil {
// special case: import genesis batch
method = backendabi.ScrollChainV2ABI.Methods["importGenesisBatch"]
_, err2 := method.Inputs.Unpack(calldata[4:])
if err2 == nil {
// genesis batch
return 0, 0, 0, nil
}
// none of "commitBatch" and "importGenesisBatch" match, give up
return 0, 0, 0, err
}
args := commitBatchArgs{}
@@ -117,3 +110,48 @@ func GetBatchRangeFromCalldataV2(calldata []byte) (uint64, uint64, uint64, error
return batchIndex, startBlock, finishBlock, err
}
// GetBatchRangeFromCalldataV1 find the block range from calldata, both inclusive.
func GetBatchRangeFromCalldataV1(calldata []byte) ([]uint64, []uint64, []uint64, error) {
var batchIndices []uint64
var startBlocks []uint64
var finishBlocks []uint64
if bytes.Equal(calldata[0:4], common.Hex2Bytes("cb905499")) {
// commitBatches
method := backendabi.ScrollChainABI.Methods["commitBatches"]
values, err := method.Inputs.Unpack(calldata[4:])
if err != nil {
return batchIndices, startBlocks, finishBlocks, err
}
args := make([]backendabi.IScrollChainBatch, len(values))
err = method.Inputs.Copy(&args, values)
if err != nil {
return batchIndices, startBlocks, finishBlocks, err
}
for i := 0; i < len(args); i++ {
batchIndices = append(batchIndices, args[i].BatchIndex)
startBlocks = append(startBlocks, args[i].Blocks[0].BlockNumber)
finishBlocks = append(finishBlocks, args[i].Blocks[len(args[i].Blocks)-1].BlockNumber)
}
} else if bytes.Equal(calldata[0:4], common.Hex2Bytes("8c73235d")) {
// commitBatch
method := backendabi.ScrollChainABI.Methods["commitBatch"]
values, err := method.Inputs.Unpack(calldata[4:])
if err != nil {
return batchIndices, startBlocks, finishBlocks, err
}
args := backendabi.IScrollChainBatch{}
err = method.Inputs.Copy(&args, values)
if err != nil {
return batchIndices, startBlocks, finishBlocks, err
}
batchIndices = append(batchIndices, args.BatchIndex)
startBlocks = append(startBlocks, args.Blocks[0].BlockNumber)
finishBlocks = append(finishBlocks, args.Blocks[len(args.Blocks)-1].BlockNumber)
} else {
return batchIndices, startBlocks, finishBlocks, errors.New("invalid selector")
}
return batchIndices, startBlocks, finishBlocks, nil
}

View File

@@ -1,6 +1,7 @@
package utils_test
import (
"os"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -33,11 +34,31 @@ func TestGetBatchRangeFromCalldataV2(t *testing.T) {
assert.Equal(t, start, uint64(10))
assert.Equal(t, finish, uint64(20))
assert.Equal(t, batchIndex, uint64(2))
// genesis batch
batchIndex, start, finish, err = utils.GetBatchRangeFromCalldataV2(common.Hex2Bytes("3fdeecb200000000000000000000000000000000000000000000000000000000000000402dcb5308098d24a37fc1487a229fcedb09fa4343ede39cbad365bc925535bb09000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000c252bc9780c4d83cf11f14b8cd03c92c4d18ce07710ba836d31d12da216c8330000000000000000000000000000000000000000000000000000000000000000000000000000000"))
assert.NoError(t, err)
assert.Equal(t, start, uint64(0))
assert.Equal(t, finish, uint64(0))
assert.Equal(t, batchIndex, uint64(0))
}
func TestGetBatchRangeFromCalldataV1(t *testing.T) {
calldata, err := os.ReadFile("../testdata/commit-batches-0x3095e91db7ba4a6fbf4654d607db322e58ff5579c502219c8024acaea74cf311.txt")
assert.NoError(t, err)
// multiple batches
batchIndices, startBlocks, finishBlocks, err := utils.GetBatchRangeFromCalldataV1(common.Hex2Bytes(string(calldata[:])))
assert.NoError(t, err)
assert.Equal(t, len(batchIndices), 5)
assert.Equal(t, len(startBlocks), 5)
assert.Equal(t, len(finishBlocks), 5)
assert.Equal(t, batchIndices[0], uint64(1))
assert.Equal(t, batchIndices[1], uint64(2))
assert.Equal(t, batchIndices[2], uint64(3))
assert.Equal(t, batchIndices[3], uint64(4))
assert.Equal(t, batchIndices[4], uint64(5))
assert.Equal(t, startBlocks[0], uint64(1))
assert.Equal(t, startBlocks[1], uint64(6))
assert.Equal(t, startBlocks[2], uint64(7))
assert.Equal(t, startBlocks[3], uint64(19))
assert.Equal(t, startBlocks[4], uint64(20))
assert.Equal(t, finishBlocks[0], uint64(5))
assert.Equal(t, finishBlocks[1], uint64(6))
assert.Equal(t, finishBlocks[2], uint64(18))
assert.Equal(t, finishBlocks[3], uint64(19))
assert.Equal(t, finishBlocks[4], uint64(20))
}

File diff suppressed because one or more lines are too long

View File

@@ -15,8 +15,8 @@ func TestEventSignature(t *testing.T) {
assert.Equal(L1RelayedMessageEventSignature, common.HexToHash("4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c"))
assert.Equal(L1FailedRelayedMessageEventSignature, common.HexToHash("99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f"))
assert.Equal(L1CommitBatchEventSignature, common.HexToHash("2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f"))
assert.Equal(L1FinalizeBatchEventSignature, common.HexToHash("26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d"))
assert.Equal(L1CommitBatchEventSignature, common.HexToHash("2cdc615c74452778c0fb6184735e014c13aad2b62774fe0b09bd1dcc2cc14a62"))
assert.Equal(L1FinalizeBatchEventSignature, common.HexToHash("9d3058a3cb9739a2527f22dd9a4138065844037d3004254952e2458d808cc364"))
assert.Equal(L1QueueTransactionEventSignature, common.HexToHash("69cfcb8e6d4192b8aba9902243912587f37e550d75c1fa801491fce26717f37e"))

View File

@@ -110,7 +110,7 @@ func action(ctx *cli.Context) error {
go utils.Loop(subCtx, 2*time.Second, l2relayer.ProcessPendingBatches)
go utils.Loop(subCtx, 60*time.Second, l2relayer.ProcessCommittedBatches)
go utils.Loop(subCtx, 2*time.Second, l2relayer.ProcessCommittedBatches)
// Finish start all rollup relayer functions.
log.Info("Start rollup-relayer successfully")

View File

@@ -376,14 +376,9 @@ func (r *Layer2Relayer) ProcessPendingBatches() {
txID := batch.Hash + "-commit"
txHash, err := r.rollupSender.SendTransaction(txID, &r.cfg.RollupContractAddress, big.NewInt(0), calldata, 0)
if err != nil {
log.Error(
"Failed to send commitBatch tx to layer1",
"index", batch.Index,
"hash", batch.Hash,
"RollupContractAddress", r.cfg.RollupContractAddress,
"calldata", common.Bytes2Hex(calldata),
"err", err,
)
if !errors.Is(err, sender.ErrNoAvailableAccount) && !errors.Is(err, sender.ErrFullPending) {
log.Error("Failed to send commitBatch tx to layer1 ", "err", err)
}
return
}
@@ -429,6 +424,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
return
case types.ProvingTaskVerified:
log.Info("Start to roll up zk proof", "hash", hash)
success := false
var parentBatchStateRoot string
if batch.Index > 0 {
@@ -442,14 +438,24 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
parentBatchStateRoot = parentBatch.StateRoot
}
defer func() {
// TODO: need to revisit this and have a more fine-grained error handling
if !success {
log.Info("Failed to upload the proof, change rollup status to RollupFinalizeFailed", "hash", hash)
if err = r.batchOrm.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizeFailed); err != nil {
log.Warn("UpdateRollupStatus failed", "hash", hash, "err", err)
}
}
}()
aggProof, err := r.batchOrm.GetVerifiedProofByHash(r.ctx, hash)
if err != nil {
log.Error("get verified proof by hash failed", "hash", hash, "err", err)
log.Warn("get verified proof by hash failed", "hash", hash, "err", err)
return
}
if err = aggProof.SanityCheck(); err != nil {
log.Error("agg_proof sanity check fails", "hash", hash, "error", err)
log.Warn("agg_proof sanity check fails", "hash", hash, "error", err)
return
}
@@ -472,18 +478,8 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
finalizeTxHash := &txHash
if err != nil {
if !errors.Is(err, sender.ErrNoAvailableAccount) && !errors.Is(err, sender.ErrFullPending) {
// This can happen normally if we try to finalize 2 or more
// batches around the same time. The 2nd tx might fail since
// the client does not see the 1st tx's updates at this point.
// TODO: add more fine-grained error handling
log.Error(
"finalizeBatchWithProof in layer1 failed",
"index", batch.Index,
"hash", batch.Hash,
"RollupContractAddress", r.cfg.RollupContractAddress,
"calldata", common.Bytes2Hex(data),
"err", err,
)
log.Error("finalizeBatchWithProof in layer1 failed",
"index", batch.Index, "hash", batch.Hash, "err", err)
}
return
}
@@ -493,31 +489,13 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
// record and sync with db, @todo handle db error
err = r.batchOrm.UpdateFinalizeTxHashAndRollupStatus(r.ctx, hash, finalizeTxHash.String(), types.RollupFinalizing)
if err != nil {
log.Error("UpdateFinalizeTxHashAndRollupStatus failed",
log.Warn("UpdateFinalizeTxHashAndRollupStatus failed",
"index", batch.Index, "batch hash", batch.Hash,
"tx hash", finalizeTxHash.String(), "err", err)
}
success = true
r.processingFinalization.Store(txID, hash)
case types.ProvingTaskFailed:
// We were unable to prove this batch. There are two possibilities:
// (a) Prover bug. In this case, we should fix and redeploy the prover.
// In the meantime, we continue to commit batches to L1 as well as
// proposing and proving chunks and batches.
// (b) Unprovable batch, e.g. proof overflow. In this case we need to
// stop the ledger, fix the limit, revert all the violating blocks,
// chunks and batches and all subsequent ones, and resume, i.e. this
// case requires manual resolution.
log.Error(
"batch proving failed",
"Index", batch.Index,
"Hash", batch.Hash,
"ProverAssignedAt", batch.ProverAssignedAt,
"ProvedAt", batch.ProvedAt,
"ProofTimeSec", batch.ProofTimeSec,
)
return
default:
log.Error("encounter unreachable case in ProcessCommittedBatches", "proving status", status)
}

View File

@@ -90,9 +90,10 @@ func testL2RelayerProcessCommittedBatches(t *testing.T) {
statuses, err := batchOrm.GetRollupStatusByHashList(context.Background(), []string{batch.Hash})
assert.NoError(t, err)
assert.Equal(t, 1, len(statuses))
// no valid proof, rollup status remains the same
assert.Equal(t, types.RollupCommitted, statuses[0])
assert.Equal(t, types.RollupFinalizeFailed, statuses[0])
err = batchOrm.UpdateRollupStatus(context.Background(), batch.Hash, types.RollupCommitted)
assert.NoError(t, err)
proof := &message.BatchProof{
Proof: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
}

View File

@@ -56,13 +56,13 @@ contract MockBridgeL1 {
/// @notice Emitted when a new batch is committed.
/// @param batchHash The hash of the batch.
event CommitBatch(uint256 indexed batchIndex, bytes32 indexed batchHash);
event CommitBatch(bytes32 indexed batchHash);
/// @notice Emitted when a batch is finalized.
/// @param batchHash The hash of the batch
/// @param stateRoot The state root on layer 2 after this batch.
/// @param withdrawRoot The merkle root on layer2 after this batch.
event FinalizeBatch(uint256 indexed batchIndex, bytes32 indexed batchHash, bytes32 stateRoot, bytes32 withdrawRoot);
event FinalizeBatch(bytes32 indexed batchHash, bytes32 stateRoot, bytes32 withdrawRoot);
/***********
* Structs *
@@ -130,7 +130,7 @@ contract MockBridgeL1 {
function commitBatch(
uint8 /*version*/,
bytes calldata _parentBatchHeader,
bytes calldata /*parentBatchHeader*/,
bytes[] memory chunks,
bytes calldata /*skippedL1MessageBitmap*/
) external {
@@ -138,17 +138,6 @@ contract MockBridgeL1 {
uint256 _chunksLength = chunks.length;
require(_chunksLength > 0, "batch is empty");
// decode batch index
uint256 headerLength = _parentBatchHeader.length;
uint256 parentBatchPtr;
uint256 parentBatchIndex;
assembly {
parentBatchPtr := mload(0x40)
calldatacopy(parentBatchPtr, _parentBatchHeader.offset, headerLength)
mstore(0x40, add(parentBatchPtr, headerLength))
parentBatchIndex := shr(192, mload(add(parentBatchPtr, 1)))
}
uint256 dataPtr;
assembly {
dataPtr := mload(0x40)
@@ -180,29 +169,18 @@ contract MockBridgeL1 {
}
bytes32 _batchHash = BatchHeaderV0Codec.computeBatchHash(batchPtr, 89);
committedBatches[0] = _batchHash;
emit CommitBatch(parentBatchIndex + 1, _batchHash);
emit CommitBatch(_batchHash);
}
function finalizeBatchWithProof(
bytes calldata batchHeader,
bytes calldata /*batchHeader*/,
bytes32 /*prevStateRoot*/,
bytes32 postStateRoot,
bytes32 withdrawRoot,
bytes calldata /*aggrProof*/
) external {
// decode batch index
uint256 headerLength = batchHeader.length;
uint256 batchPtr;
uint256 batchIndex;
assembly {
batchPtr := mload(0x40)
calldatacopy(batchPtr, batchHeader.offset, headerLength)
mstore(0x40, add(batchPtr, headerLength))
batchIndex := shr(192, mload(add(batchPtr, 1)))
}
bytes32 _batchHash = committedBatches[0];
emit FinalizeBatch(batchIndex, _batchHash, postStateRoot, withdrawRoot);
emit FinalizeBatch(_batchHash, postStateRoot, withdrawRoot);
}
/**********************

View File

@@ -37,7 +37,7 @@ COPY . .
RUN cp -r ./common/libzkp/interface ./coordinator/internal/logic/verifier/lib
COPY --from=zkp-builder /app/target/release/libzkp.so ./coordinator/internal/logic/verifier/lib/
COPY --from=zkp-builder /app/target/release/libzktrie.so ./coordinator/internal/logic/verifier/lib/
RUN cd ./coordinator && make coordinator_skip_libzkp && mv ./build/bin/coordinator /bin/coordinator && mv internal/logic/verifier/lib /bin/
RUN cd ./coordinator && go build -v -p 4 -o /bin/coordinator ./cmd && mv internal/logic/verifier/lib /bin/
# Pull coordinator into a second stage deploy alpine container
FROM ubuntu:20.04
@@ -46,6 +46,6 @@ ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/src/coordinator/internal/logic/verifier/li
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 /bin/
RUN /bin/coordinator --version
ENTRYPOINT ["/bin/coordinator"]

View File

@@ -1,31 +0,0 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.19 as base
WORKDIR /src
COPY go.work* ./
COPY ./bridge/go.* ./bridge/
COPY ./common/go.* ./common/
COPY ./coordinator/go.* ./coordinator/
COPY ./database/go.* ./database/
COPY ./prover-stats-api/go.* ./prover-stats-api/
COPY ./prover/go.* ./prover/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
# Support mainland environment.
#ENV GOPROXY="https://goproxy.cn,direct"
RUN go mod download -x
# Build prover-stats-api
FROM base as builder
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
cd /src/prover-stats-api/cmd/ && go build -v -p 4 -o /bin/prover-stats-api
# Pull prover-stats-api into a second stage deploy alpine container \
FROM alpine:latest
COPY --from=builder /bin/prover-stats-api /bin/
ENTRYPOINT ["prover-stats-api"]

View File

@@ -83,9 +83,7 @@ func (c *Cmd) Write(data []byte) (int, error) {
out := string(data)
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), "info") {
} else if strings.Contains(strings.ToLower(out), "error") || 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{}) {

View File

@@ -32,7 +32,7 @@ dependencies = [
[[package]]
name = "aggregator"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"ark-std",
"env_logger 0.10.0",
@@ -432,7 +432,7 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "bus-mapping"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"eth-types",
"ethers-core",
@@ -630,12 +630,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "convert_case"
version = "0.6.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
dependencies = [
"unicode-segmentation",
]
checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8"
[[package]]
name = "core-foundation-sys"
@@ -1048,7 +1045,7 @@ dependencies = [
[[package]]
name = "eth-types"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"ethers-core",
"ethers-signers",
@@ -1141,12 +1138,13 @@ dependencies = [
[[package]]
name = "ethers-core"
version = "0.17.0"
source = "git+https://github.com/scroll-tech/ethers-rs.git?branch=v0.17.0#739ec9a0df8daf536937739c87e85612bd73212f"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ebdd63c828f58aa067f40f9adcbea5e114fb1f90144b3a1e2858e0c9b1ff4e8"
dependencies = [
"arrayvec",
"bytes",
"chrono",
"convert_case 0.6.0",
"convert_case 0.5.0",
"elliptic-curve",
"ethabi",
"fastrlp",
@@ -1225,7 +1223,7 @@ dependencies = [
[[package]]
name = "external-tracer"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"eth-types",
"geth-utils",
@@ -1438,7 +1436,7 @@ dependencies = [
[[package]]
name = "gadgets"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"digest 0.7.6",
"eth-types",
@@ -1478,7 +1476,7 @@ dependencies = [
[[package]]
name = "geth-utils"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"env_logger 0.9.3",
"gobuild 0.1.0-alpha.2 (git+https://github.com/scroll-tech/gobuild.git)",
@@ -2076,7 +2074,7 @@ dependencies = [
[[package]]
name = "keccak256"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"env_logger 0.9.3",
"eth-types",
@@ -2263,7 +2261,7 @@ dependencies = [
[[package]]
name = "mock"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"eth-types",
"ethers-core",
@@ -2278,7 +2276,7 @@ dependencies = [
[[package]]
name = "mpt-zktrie"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"bus-mapping",
"eth-types",
@@ -2754,7 +2752,7 @@ dependencies = [
[[package]]
name = "prover"
version = "0.4.0"
source = "git+https://github.com/scroll-tech/scroll-prover?tag=v0.5.12#ef945901bee26c4b79be8af60e259443392368fa"
source = "git+https://github.com/scroll-tech/scroll-prover?tag=v0.5.1#15aac6e1484a42f723098fbc9d8783f374e7e90a"
dependencies = [
"aggregator",
"anyhow",
@@ -3623,7 +3621,7 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "snark-verifier"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#12c306ec57849921e690221b10b8a08189868d4a"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#f8bdcbee60348e5c996c04f19ff30522e6b276b0"
dependencies = [
"bytes",
"ethereum-types 0.14.1",
@@ -3647,7 +3645,7 @@ dependencies = [
[[package]]
name = "snark-verifier-sdk"
version = "0.0.1"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#12c306ec57849921e690221b10b8a08189868d4a"
source = "git+https://github.com/scroll-tech/snark-verifier?branch=develop#f8bdcbee60348e5c996c04f19ff30522e6b276b0"
dependencies = [
"bincode",
"env_logger 0.10.0",
@@ -4039,7 +4037,7 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "types"
version = "0.4.0"
source = "git+https://github.com/scroll-tech/scroll-prover?tag=v0.5.12#ef945901bee26c4b79be8af60e259443392368fa"
source = "git+https://github.com/scroll-tech/scroll-prover?tag=v0.5.1#15aac6e1484a42f723098fbc9d8783f374e7e90a"
dependencies = [
"base64 0.13.1",
"blake2",
@@ -4084,12 +4082,6 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-xid"
version = "0.2.4"
@@ -4490,7 +4482,7 @@ checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
[[package]]
name = "zkevm-circuits"
version = "0.1.0"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?tag=v0.5.12#554bdcf00334bab45670b8daa72d687a7ff2b919"
source = "git+https://github.com/scroll-tech/zkevm-circuits.git?branch=develop#2855c13b5d3e6ec4056f823f56a33bf25d0080bb"
dependencies = [
"array-init",
"bus-mapping",

View File

@@ -7,8 +7,6 @@ edition = "2021"
[lib]
crate-type = ["cdylib"]
[patch.crates-io]
ethers-core = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v0.17.0" }
[patch."https://github.com/privacy-scaling-explorations/halo2.git"]
halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "develop" }
[patch."https://github.com/privacy-scaling-explorations/poseidon.git"]
@@ -20,8 +18,8 @@ maingate = { git = "https://github.com/scroll-tech/halo2wrong", branch = "halo2-
halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "0.3.1-derive-serde" }
[dependencies]
prover = { git = "https://github.com/scroll-tech/scroll-prover", tag = "v0.5.12" }
types = { git = "https://github.com/scroll-tech/scroll-prover", tag = "v0.5.12" }
prover = { git = "https://github.com/scroll-tech/scroll-prover", tag = "v0.5.1" }
types = { git = "https://github.com/scroll-tech/scroll-prover", tag = "v0.5.1" }
halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "develop" }
log = "0.4"
@@ -35,6 +33,8 @@ once_cell = "1.8.0"
[profile.test]
opt-level = 3
# debug-assertions = true
[profile.release]
opt-level = 3
# debug-assertions = true

View File

@@ -8,7 +8,7 @@ use prover::{
use std::{cell::OnceCell, panic, ptr::null};
use types::eth::BlockTrace;
static mut PROVER: OnceCell<Prover> = OnceCell::new();
static mut BATCH_PROVER: OnceCell<Prover> = OnceCell::new();
static mut VERIFIER: OnceCell<Verifier> = OnceCell::new();
/// # Safety
@@ -19,7 +19,7 @@ pub unsafe extern "C" fn init_batch_prover(params_dir: *const c_char) {
let params_dir = c_char_to_str(params_dir);
let prover = Prover::from_params_dir(params_dir);
PROVER.set(prover).unwrap();
BATCH_PROVER.set(prover).unwrap();
}
/// # Safety
@@ -54,7 +54,7 @@ pub unsafe extern "C" fn gen_batch_proof(
.collect();
let proof_result = panic::catch_unwind(|| {
let proof = PROVER
let proof = BATCH_PROVER
.get_mut()
.unwrap()
.gen_agg_evm_proof(chunk_hashes_proofs, None, OUTPUT_DIR.as_deref())

View File

@@ -0,0 +1,90 @@
use crate::utils::{c_char_to_str, c_char_to_vec, vec_to_c_char, OUTPUT_DIR};
use libc::c_char;
use prover::{
aggregator::{Prover, Verifier},
utils::{chunk_trace_to_witness_block, init_env_and_log},
BatchProof, ChunkHash, ChunkProof,
};
use std::{cell::OnceCell, panic, ptr::null};
use types::eth::BlockTrace;
static mut BATCH_PROVER: OnceCell<Prover> = OnceCell::new();
static mut VERIFIER: OnceCell<Verifier> = OnceCell::new();
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn init_batch_prover(params_dir: *const c_char) {
init_env_and_log("ffi_batch_prove");
let params_dir = c_char_to_str(params_dir);
let prover = Prover::from_params_dir(params_dir);
BATCH_PROVER.set(prover).unwrap();
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn init_batch_verifier(params_dir: *const c_char, assets_dir: *const c_char) {
init_env_and_log("ffi_batch_verify");
let params_dir = c_char_to_str(params_dir);
let assets_dir = c_char_to_str(assets_dir);
let verifier = Verifier::from_dirs(params_dir, assets_dir);
VERIFIER.set(verifier).unwrap();
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn gen_batch_proof(
chunk_hashes: *const c_char,
chunk_proofs: *const c_char,
) -> *const c_char {
let chunk_hashes = c_char_to_vec(chunk_hashes);
let chunk_proofs = c_char_to_vec(chunk_proofs);
let chunk_hashes = serde_json::from_slice::<Vec<ChunkHash>>(&chunk_hashes).unwrap();
let chunk_proofs = serde_json::from_slice::<Vec<ChunkProof>>(&chunk_proofs).unwrap();
assert_eq!(chunk_hashes.len(), chunk_proofs.len());
let chunk_hashes_proofs = chunk_hashes
.into_iter()
.zip(chunk_proofs.into_iter())
.collect();
let proof_result = panic::catch_unwind(|| {
let proof = BATCH_PROVER
.get_mut()
.unwrap()
.gen_agg_evm_proof(chunk_hashes_proofs, None, OUTPUT_DIR.as_deref())
.unwrap();
serde_json::to_vec(&proof).unwrap()
});
proof_result.map_or(null(), vec_to_c_char)
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn verify_batch_proof(proof: *const c_char) -> c_char {
let proof = c_char_to_vec(proof);
let proof = serde_json::from_slice::<BatchProof>(proof.as_slice()).unwrap();
let verified = panic::catch_unwind(|| VERIFIER.get().unwrap().verify_agg_evm_proof(proof));
verified.unwrap_or(false) as c_char
}
// This function is only used for debugging on Go side.
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn block_traces_to_chunk_info(block_traces: *const c_char) -> *const c_char {
let block_traces = c_char_to_vec(block_traces);
let block_traces = serde_json::from_slice::<Vec<BlockTrace>>(&block_traces).unwrap();
let witness_block = chunk_trace_to_witness_block(block_traces).unwrap();
let chunk_info = ChunkHash::from_witness_block(&witness_block, false);
let chunk_info_bytes = serde_json::to_vec(&chunk_info).unwrap();
vec_to_c_char(chunk_info_bytes)
}

View File

@@ -8,7 +8,7 @@ use prover::{
use std::{cell::OnceCell, panic, ptr::null};
use types::eth::BlockTrace;
static mut PROVER: OnceCell<Prover> = OnceCell::new();
static mut CHUNK_PROVER: OnceCell<Prover> = OnceCell::new();
static mut VERIFIER: OnceCell<Verifier> = OnceCell::new();
/// # Safety
@@ -19,7 +19,7 @@ pub unsafe extern "C" fn init_chunk_prover(params_dir: *const c_char) {
let params_dir = c_char_to_str(params_dir);
let prover = Prover::from_params_dir(params_dir);
PROVER.set(prover).unwrap();
CHUNK_PROVER.set(prover).unwrap();
}
/// # Safety
@@ -42,7 +42,7 @@ pub unsafe extern "C" fn gen_chunk_proof(block_traces: *const c_char) -> *const
let block_traces = serde_json::from_slice::<Vec<BlockTrace>>(&block_traces).unwrap();
let proof_result = panic::catch_unwind(|| {
let proof = PROVER
let proof = CHUNK_PROVER
.get_mut()
.unwrap()
.gen_chunk_proof(block_traces, None, OUTPUT_DIR.as_deref())

View File

@@ -0,0 +1,65 @@
use crate::utils::{c_char_to_str, c_char_to_vec, vec_to_c_char, OUTPUT_DIR};
use libc::c_char;
use prover::{
utils::init_env_and_log,
zkevm::{Prover, Verifier},
ChunkProof,
};
use std::{cell::OnceCell, panic, ptr::null};
use types::eth::BlockTrace;
static mut CHUNK_PROVER: OnceCell<Prover> = OnceCell::new();
static mut VERIFIER: OnceCell<Verifier> = OnceCell::new();
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn init_chunk_prover(params_dir: *const c_char) {
init_env_and_log("ffi_chunk_prove");
let params_dir = c_char_to_str(params_dir);
let prover = Prover::from_params_dir(params_dir);
CHUNK_PROVER.set(prover).unwrap();
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn init_chunk_verifier(params_dir: *const c_char, assets_dir: *const c_char) {
init_env_and_log("ffi_chunk_verify");
let params_dir = c_char_to_str(params_dir);
let assets_dir = c_char_to_str(assets_dir);
let verifier = Verifier::from_dirs(params_dir, assets_dir);
VERIFIER.set(verifier).unwrap();
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn gen_chunk_proof(block_traces: *const c_char) -> *const c_char {
let block_traces = c_char_to_vec(block_traces);
let block_traces = serde_json::from_slice::<Vec<BlockTrace>>(&block_traces).unwrap();
let proof_result = panic::catch_unwind(|| {
let proof = CHUNK_PROVER
.get_mut()
.unwrap()
.gen_chunk_proof(block_traces, None, OUTPUT_DIR.as_deref())
.unwrap();
serde_json::to_vec(&proof).unwrap()
});
proof_result.map_or(null(), vec_to_c_char)
}
/// # Safety
#[no_mangle]
pub unsafe extern "C" fn verify_chunk_proof(proof: *const c_char) -> c_char {
let proof = c_char_to_vec(proof);
let proof = serde_json::from_slice::<ChunkProof>(proof.as_slice()).unwrap();
let verified = panic::catch_unwind(|| VERIFIER.get().unwrap().verify_chunk_proof(proof));
verified.unwrap_or(false) as c_char
}

View File

@@ -1,5 +1,5 @@
#![feature(once_cell)]
mod batch;
mod chunk;
mod prove_batch;
mod prove_chunk;
mod utils;

View File

@@ -169,7 +169,7 @@ func TestBatchHeaderEncode(t *testing.T) {
assert.NotNil(t, batchHeader)
bytes = batchHeader.Encode()
assert.Equal(t, 121, len(bytes))
assert.Equal(t, "010000000000000001000000000000000b000000000000000b34f419ce7e882295bdb5aec6cce56ffa788a5fed4744d7fbd77e4acbf409f1ca4136709aabc8a23aa17fbcc833da2f7857d3c2884feec9aae73429c135f9498500000000000000000000000000000000000000000000000000000000000003ff", common.Bytes2Hex(bytes))
assert.Equal(t, "010000000000000001000000000000000b000000000000000b457a9e90e8e51ba2de2f66c6b589540b88cf594dac7fa7d04b99cdcfecf24e384136709aabc8a23aa17fbcc833da2f7857d3c2884feec9aae73429c135f9498500000000000000000000000000000000000000000000000000000000000003ff", common.Bytes2Hex(bytes))
}
func TestBatchHeaderHash(t *testing.T) {
@@ -230,7 +230,7 @@ func TestBatchHeaderHash(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, batchHeader)
hash = batchHeader.Hash()
assert.Equal(t, "1c3007880f0eafe74572ede7d164ff1ee5376e9ac9bff6f7fb837b2630cddc9a", common.Bytes2Hex(hash.Bytes()))
assert.Equal(t, "0ec9547c6645d5f0c1254e121f49e93f54525cfda5bfb2236440fb3470f48902", common.Bytes2Hex(hash.Bytes()))
}
func TestBatchHeaderDecode(t *testing.T) {

View File

@@ -36,17 +36,6 @@ func (w *WrappedBlock) NumL1Messages(totalL1MessagePoppedBefore uint64) uint64 {
return *lastQueueIndex - totalL1MessagePoppedBefore + 1
}
// NumL2Transactions returns the number of L2 transactions in this block.
func (w *WrappedBlock) NumL2Transactions() uint64 {
var count uint64
for _, txData := range w.Transactions {
if txData.Type != types.L1MessageTxType {
count++
}
}
return count
}
// Encode encodes the WrappedBlock into RollupV2 BlockContext Encoding.
func (w *WrappedBlock) Encode(totalL1MessagePoppedBefore uint64) ([]byte, error) {
bytes := make([]byte, 60)
@@ -54,25 +43,20 @@ func (w *WrappedBlock) Encode(totalL1MessagePoppedBefore uint64) ([]byte, error)
if !w.Header.Number.IsUint64() {
return nil, errors.New("block number is not uint64")
}
if len(w.Transactions) > math.MaxUint16 {
return nil, errors.New("number of transactions exceeds max uint16")
}
// note: numL1Messages includes skipped messages
numL1Messages := w.NumL1Messages(totalL1MessagePoppedBefore)
if numL1Messages > math.MaxUint16 {
return nil, errors.New("number of L1 messages exceeds max uint16")
}
// note: numTransactions includes skipped messages
numL2Transactions := w.NumL2Transactions()
numTransactions := numL1Messages + numL2Transactions
if numTransactions > math.MaxUint16 {
return nil, errors.New("number of transactions exceeds max uint16")
}
binary.BigEndian.PutUint64(bytes[0:], w.Header.Number.Uint64())
binary.BigEndian.PutUint64(bytes[8:], w.Header.Time)
// TODO: [16:47] Currently, baseFee is 0, because we disable EIP-1559.
binary.BigEndian.PutUint64(bytes[48:], w.Header.GasLimit)
binary.BigEndian.PutUint16(bytes[56:], uint16(numTransactions))
binary.BigEndian.PutUint16(bytes[56:], uint16(len(w.Transactions)))
binary.BigEndian.PutUint16(bytes[58:], uint16(numL1Messages))
return bytes, nil

View File

@@ -65,10 +65,9 @@ func TestChunkEncode(t *testing.T) {
hexString = hex.EncodeToString(bytes)
assert.NoError(t, err)
assert.Equal(t, 97, len(bytes))
assert.Equal(t, "01000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a1200000c000b00000020df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e1058080808080", hexString)
assert.Equal(t, "01000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a12000002000b00000020df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e1058080808080", hexString)
// Test case 5: when the chunk contains two blocks each with 1 L1MsgTx
// TODO: revise this test, we cannot reuse the same L1MsgTx twice
chunk = &Chunk{
Blocks: []*WrappedBlock{
wrappedBlock2,
@@ -79,7 +78,7 @@ func TestChunkEncode(t *testing.T) {
hexString = hex.EncodeToString(bytes)
assert.NoError(t, err)
assert.Equal(t, 193, len(bytes))
assert.Equal(t, "02000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a1200000c000b000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a12000001000000000020df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e105808080808000000020df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e1058080808080", hexString)
assert.Equal(t, "02000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a12000002000b000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a12000002000000000020df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e105808080808000000020df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e1058080808080", hexString)
}
func TestChunkHash(t *testing.T) {
@@ -134,5 +133,5 @@ func TestChunkHash(t *testing.T) {
}
hash, err = chunk.Hash(0)
assert.NoError(t, err)
assert.Equal(t, "0x2eb7dd63bf8fc29a0f8c10d16c2ae6f9da446907c79d50f5c164d30dc8526b60", hash.Hex())
assert.Equal(t, "0x42967825696a129e7a83f082097aca982747480956dcaa448c9296e795c9a91a", hash.Hex())
}

View File

@@ -126,7 +126,7 @@ const (
ProvingTaskUnassigned
// ProvingTaskAssigned : proving_task is assigned to be proved
ProvingTaskAssigned
// ProvingTaskProved DEPRECATED: proof has been returned by prover
// ProvingTaskProved : proof has been returned by prover
ProvingTaskProved
// ProvingTaskVerified : proof is valid
ProvingTaskVerified

View File

@@ -33,7 +33,7 @@ func (r ProofType) String() string {
case ProofTypeBatch:
return "proof type batch"
default:
return fmt.Sprintf("illegal proof type: %d", r)
return "illegal proof type"
}
}
@@ -60,8 +60,6 @@ type AuthMsg struct {
type Identity struct {
// ProverName the prover name
ProverName string `json:"prover_name"`
// ProverVersion the prover version
ProverVersion string `json:"prover_version"`
// Challenge unique challenge generated by manager
Challenge string `json:"challenge"`
}

View File

@@ -15,9 +15,8 @@ func TestAuthMessageSignAndVerify(t *testing.T) {
authMsg := &AuthMsg{
Identity: &Identity{
Challenge: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTEwMzgxNzUsIm9yaWdfaWF0IjoxNjkxMDM0NTc1fQ.HybBMsEJFhyZqtIa2iVcHUP7CEFttf708jmTMAImAWA",
ProverName: "test",
ProverVersion: "v1.0.0",
Challenge: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTEwMzgxNzUsIm9yaWdfaWF0IjoxNjkxMDM0NTc1fQ.HybBMsEJFhyZqtIa2iVcHUP7CEFttf708jmTMAImAWA",
ProverName: "test",
},
}
assert.NoError(t, authMsg.SignWithKey(privkey))
@@ -46,15 +45,14 @@ func TestGenerateToken(t *testing.T) {
func TestIdentityHash(t *testing.T) {
identity := &Identity{
Challenge: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTEwMzM0MTksIm9yaWdfaWF0IjoxNjkxMDI5ODE5fQ.EhkLZsj__rNPVC3ZDYBtvdh0nB8mmM_Hl82hObaIWOs",
ProverName: "test",
ProverVersion: "v1.0.0",
Challenge: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTEwMzM0MTksIm9yaWdfaWF0IjoxNjkxMDI5ODE5fQ.EhkLZsj__rNPVC3ZDYBtvdh0nB8mmM_Hl82hObaIWOs",
ProverName: "test",
}
hash, err := identity.Hash()
assert.NoError(t, err)
expectedHash := "83f5e0ad023e9c1de639ab07b9b4cb972ec9dbbd2524794c533a420a5b137721"
expectedHash := "7373bb57ab7c01307d86fec55e088e00c526d82d9d1303fa4a189ff6ea95fbe2"
assert.Equal(t, expectedHash, hex.EncodeToString(hash))
}
@@ -118,7 +116,7 @@ func TestProveTypeString(t *testing.T) {
assert.Equal(t, "proof type batch", proofTypeBatch.String())
illegalProof := ProofType(3)
assert.Equal(t, "illegal proof type: 3", illegalProof.String())
assert.Equal(t, "illegal proof type", illegalProof.String())
}
func TestProofMsgPublicKey(t *testing.T) {

View File

@@ -20,17 +20,12 @@ var (
MessageRelayerApp MockAppName = "message-relayer-test"
// RollupRelayerApp the name of mock rollup-relayer app.
RollupRelayerApp MockAppName = "rollup-relayer-test"
// DBCliApp the name of mock database app.
DBCliApp MockAppName = "db_cli-test"
// CoordinatorApp the name of mock coordinator app.
CoordinatorApp MockAppName = "coordinator-test"
// ChunkProverApp the name of mock chunk prover app.
ChunkProverApp MockAppName = "chunkProver-test"
// BatchProverApp the name of mock batch prover app.
BatchProverApp MockAppName = "batchProver-test"
// DBCliApp the name of mock database app.
DBCliApp MockAppName = "db_cli-test"
// ProverApp the name of mock prover app.
ProverApp MockAppName = "prover-test"
)
// RegisterSimulation register initializer function for integration-test.

View File

@@ -3,10 +3,9 @@ package version
import (
"fmt"
"runtime/debug"
"strings"
)
var tag = "v4.1.31"
var tag = "v4.1.0"
var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {
@@ -20,29 +19,11 @@ var commit = func() string {
}
}
}
// Set default value for integration test.
return "000000"
return ""
}()
// ZkVersion is commit-id of common/libzkp/impl/cargo.lock/scroll-prover and halo2, contacted by a "-"
// The default `000000-000000` is set for integration test, and will be overwritten by coordinator's & prover's actual compilations (see their Makefiles).
var ZkVersion = "000000-000000"
// ZkVersion is commit-id of common/libzkp/impl/cargo.lock/scroll-prover
var ZkVersion string
// Version denote the version of scroll protocol, including the l2geth, relayer, coordinator, prover, contracts and etc.
var Version = fmt.Sprintf("%s-%s-%s", tag, commit, ZkVersion)
// CheckScrollProverVersion check the "scroll-prover" version, if it's different from the local one, return false
func CheckScrollProverVersion(proverVersion string) bool {
// note the the version is in fact in the format of "tag-commit-scroll_prover-halo2",
// so split-by-'-' length should be 4
remote := strings.Split(proverVersion, "-")
if len(remote) != 4 {
return false
}
local := strings.Split(Version, "-")
if len(local) != 4 {
return false
}
// compare the `scroll_prover` version
return remote[2] == local[2]
}

View File

@@ -1,16 +1,16 @@
{
"ProxyAdmin": "0x95ec888F34b23063aeaB47c8E229B3a25DBF8e4F",
"ProxyAdmin": null,
"ZKRollup": {
"implementation": null,
"proxy": null
},
"L1ScrollMessenger": {
"implementation": "0xC71532468A74084cfd824c0445E96f9A2dc3Bd7E",
"proxy": "0x50c7d3e7f7c656493D1D76aaa1a836CedfCBB16A"
"implementation": null,
"proxy": null
},
"L1GatewayRouter": {
"implementation": "0x5431937CF9cb638df5e3587Ae0a2F62130CEE27e",
"proxy": "0x13FBE0D0e5552b8c9c4AE9e2435F38f37355998a"
"implementation": null,
"proxy": null
},
"L1StandardERC20Gateway": {
"implementation": null,
@@ -19,9 +19,5 @@
"L1WETHGateway": {
"implementation": null,
"proxy": null
},
"L1USDCGateway": {
"implementation": "0x2Cf090069Bc47CA931f350fe1D0a160dba4c7C53",
"proxy": "0xeED47C513265cefe6846Dd51B624F1102A9a89d3"
}
}

View File

@@ -1,16 +1,13 @@
{
"ProxyAdmin": "0x95ec888F34b23063aeaB47c8E229B3a25DBF8e4F",
"ProxyAdmin": null,
"WETH": null,
"Whitelist": null,
"ScrollStandardERC20": null,
"ScrollStandardERC20Factory": null,
"L2ScrollMessenger": {
"implementation": "0x45BA70424D61e6A0D2A5FF9093927350471A2728",
"proxy": "0xBa50f5340FB9F3Bd074bD638c9BE13eCB36E603d"
},
"L2ScrollMessenger": null,
"L2GatewayRouter": {
"implementation": "0x0378D0F56f13f018b8d4803f09349781e143453e",
"proxy": "0x9aD3c5617eCAa556d6E166787A97081907171230"
"implementation": null,
"proxy": null
},
"L2StandardERC20Gateway": {
"implementation": null,
@@ -19,9 +16,5 @@
"L2WETHGateway": {
"implementation": null,
"proxy": null
},
"L2USDCGateway": {
"implementation": "0xCad8ba59173F3d6b3d15E8eeE2CB5C8b43e50fC0",
"proxy": "0x78a5dacf40E26c21A69fA3D701F9e75f19FD7113"
}
}

View File

@@ -533,7 +533,7 @@ Emitted when some ERC1155 token is refunded.
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token)
event UpdateTokenMapping(address _l1Token, address _l2Token)
```
Emitted when token mapping for ERC1155 token is updated.
@@ -544,9 +544,8 @@ Emitted when token mapping for ERC1155 token is updated.
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC1155 token in layer 1. |
| oldL2Token `indexed` | address | The address of the old corresponding ERC1155 token in layer 2. |
| newL2Token `indexed` | address | The address of the new corresponding ERC1155 token in layer 2. |
| _l1Token | address | The address of ERC1155 token on layer 1. |
| _l2Token | address | The address of corresponding ERC1155 token on layer 2. |

View File

@@ -472,7 +472,7 @@ Emitted when some ERC721 token is refunded.
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token)
event UpdateTokenMapping(address _l1Token, address _l2Token)
```
Emitted when token mapping for ERC721 token is updated.
@@ -483,9 +483,8 @@ Emitted when token mapping for ERC721 token is updated.
| Name | Type | Description |
|---|---|---|
| l1Token `indexed` | address | The address of ERC721 token in layer 1. |
| oldL2Token `indexed` | address | The address of the old corresponding ERC721 token in layer 2. |
| newL2Token `indexed` | address | The address of the new corresponding ERC721 token in layer 2. |
| _l1Token | address | The address of ERC721 token on layer 1. |
| _l2Token | address | The address of corresponding ERC721 token on layer 2. |

View File

@@ -350,7 +350,7 @@ Request ERC20 token transfer from users to gateways.
### setDefaultERC20Gateway
```solidity
function setDefaultERC20Gateway(address _newDefaultERC20Gateway) external nonpayable
function setDefaultERC20Gateway(address _defaultERC20Gateway) external nonpayable
```
Update the address of default ERC20 gateway contract.
@@ -361,7 +361,7 @@ Update the address of default ERC20 gateway contract.
| Name | Type | Description |
|---|---|---|
| _newDefaultERC20Gateway | address | undefined |
| _defaultERC20Gateway | address | The address to update. |
### setERC20Gateway
@@ -383,7 +383,7 @@ Update the mapping from token address to gateway address.
### setETHGateway
```solidity
function setETHGateway(address _newEthGateway) external nonpayable
function setETHGateway(address _ethGateway) external nonpayable
```
Update the address of ETH gateway contract.
@@ -394,7 +394,7 @@ Update the address of ETH gateway contract.
| Name | Type | Description |
|---|---|---|
| _newEthGateway | address | undefined |
| _ethGateway | address | The address to update. |
### transferOwnership
@@ -567,7 +567,7 @@ Emitted when some ETH is refunded.
### SetDefaultERC20Gateway
```solidity
event SetDefaultERC20Gateway(address indexed oldDefaultERC20Gateway, address indexed newDefaultERC20Gateway)
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway)
```
Emitted when the address of default ERC20 Gateway is updated.
@@ -578,13 +578,12 @@ Emitted when the address of default ERC20 Gateway is updated.
| Name | Type | Description |
|---|---|---|
| oldDefaultERC20Gateway `indexed` | address | undefined |
| newDefaultERC20Gateway `indexed` | address | undefined |
| defaultERC20Gateway `indexed` | address | undefined |
### SetERC20Gateway
```solidity
event SetERC20Gateway(address indexed token, address indexed oldGateway, address indexed newGateway)
event SetERC20Gateway(address indexed token, address indexed gateway)
```
Emitted when the `gateway` for `token` is updated.
@@ -596,13 +595,12 @@ Emitted when the `gateway` for `token` is updated.
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | undefined |
| oldGateway `indexed` | address | undefined |
| newGateway `indexed` | address | undefined |
| gateway `indexed` | address | undefined |
### SetETHGateway
```solidity
event SetETHGateway(address indexed oldETHGateway, address indexed newEthGateway)
event SetETHGateway(address indexed ethGateway)
```
Emitted when the address of ETH Gateway is updated.
@@ -613,8 +611,7 @@ Emitted when the address of ETH Gateway is updated.
| Name | Type | Description |
|---|---|---|
| oldETHGateway `indexed` | address | undefined |
| newEthGateway `indexed` | address | undefined |
| ethGateway `indexed` | address | undefined |

View File

@@ -423,7 +423,7 @@ Update fee vault contract.
### updateMaxReplayTimes
```solidity
function updateMaxReplayTimes(uint256 _newMaxReplayTimes) external nonpayable
function updateMaxReplayTimes(uint256 _maxReplayTimes) external nonpayable
```
Update max replay times.
@@ -434,7 +434,7 @@ Update max replay times.
| Name | Type | Description |
|---|---|---|
| _newMaxReplayTimes | uint256 | The new max replay times. |
| _maxReplayTimes | uint256 | The new max replay times. |
### xDomainMessageSender
@@ -595,7 +595,7 @@ Emitted when owner updates fee vault contract.
### UpdateMaxReplayTimes
```solidity
event UpdateMaxReplayTimes(uint256 oldMaxReplayTimes, uint256 newMaxReplayTimes)
event UpdateMaxReplayTimes(uint256 maxReplayTimes)
```
Emitted when the maximum number of times each message can be replayed is updated.
@@ -606,8 +606,7 @@ Emitted when the maximum number of times each message can be replayed is updated
| Name | Type | Description |
|---|---|---|
| oldMaxReplayTimes | uint256 | undefined |
| newMaxReplayTimes | uint256 | undefined |
| maxReplayTimes | uint256 | undefined |

View File

@@ -214,34 +214,6 @@ function onDropMessage(bytes _message) external payable
|---|---|---|
| _message | bytes | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
@@ -259,22 +231,6 @@ The address of L1GatewayRouter/L2GatewayRouter contract.
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
## Events
@@ -337,23 +293,6 @@ event Initialized(uint8 version)
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC20
```solidity

View File

@@ -212,34 +212,6 @@ function onDropMessage(bytes _message) external payable
|---|---|---|
| _message | bytes | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
@@ -257,22 +229,6 @@ The address of L1GatewayRouter/L2GatewayRouter contract.
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
## Events
@@ -335,23 +291,6 @@ event Initialized(uint8 version)
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### RefundERC20
```solidity

View File

@@ -458,7 +458,7 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token)
event UpdateTokenMapping(address _l2Token, address _l1Token)
```
Emitted when token mapping for ERC1155 token is updated.
@@ -469,9 +469,8 @@ Emitted when token mapping for ERC1155 token is updated.
| Name | Type | Description |
|---|---|---|
| l2Token `indexed` | address | The address of corresponding ERC1155 token in layer 2. |
| oldL1Token `indexed` | address | The address of the old corresponding ERC1155 token in layer 1. |
| newL1Token `indexed` | address | The address of the new corresponding ERC1155 token in layer 1. |
| _l2Token | address | The address of corresponding ERC1155 token on layer 2. |
| _l1Token | address | The address of ERC1155 token on layer 1. |
### WithdrawERC1155

View File

@@ -400,7 +400,7 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn
### UpdateTokenMapping
```solidity
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token)
event UpdateTokenMapping(address _l2Token, address _l1Token)
```
Emitted when token mapping for ERC721 token is updated.
@@ -411,9 +411,8 @@ Emitted when token mapping for ERC721 token is updated.
| Name | Type | Description |
|---|---|---|
| l2Token `indexed` | address | The address of corresponding ERC721 token in layer 2. |
| oldL1Token `indexed` | address | The address of the old corresponding ERC721 token in layer 1. |
| newL1Token `indexed` | address | The address of the new corresponding ERC721 token in layer 1. |
| _l2Token | address | The address of corresponding ERC721 token on layer 2. |
| _l1Token | address | The address of ERC721 token on layer 1. |
### WithdrawERC721

View File

@@ -220,7 +220,7 @@ function renounceOwnership() external nonpayable
### setDefaultERC20Gateway
```solidity
function setDefaultERC20Gateway(address _newDefaultERC20Gateway) external nonpayable
function setDefaultERC20Gateway(address _defaultERC20Gateway) external nonpayable
```
Update the address of default ERC20 gateway contract.
@@ -231,7 +231,7 @@ Update the address of default ERC20 gateway contract.
| Name | Type | Description |
|---|---|---|
| _newDefaultERC20Gateway | address | The address to update. |
| _defaultERC20Gateway | address | The address to update. |
### setERC20Gateway
@@ -253,7 +253,7 @@ Update the mapping from token address to gateway address.
### setETHGateway
```solidity
function setETHGateway(address _newEthGateway) external nonpayable
function setETHGateway(address _ethGateway) external nonpayable
```
Update the address of ETH gateway contract.
@@ -264,7 +264,7 @@ Update the address of ETH gateway contract.
| Name | Type | Description |
|---|---|---|
| _newEthGateway | address | The address to update. |
| _ethGateway | address | The address to update. |
### transferOwnership
@@ -473,7 +473,7 @@ event OwnershipTransferred(address indexed previousOwner, address indexed newOwn
### SetDefaultERC20Gateway
```solidity
event SetDefaultERC20Gateway(address indexed oldDefaultERC20Gateway, address indexed newDefaultERC20Gateway)
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway)
```
Emitted when the address of default ERC20 Gateway is updated.
@@ -484,13 +484,12 @@ Emitted when the address of default ERC20 Gateway is updated.
| Name | Type | Description |
|---|---|---|
| oldDefaultERC20Gateway `indexed` | address | undefined |
| newDefaultERC20Gateway `indexed` | address | undefined |
| defaultERC20Gateway `indexed` | address | undefined |
### SetERC20Gateway
```solidity
event SetERC20Gateway(address indexed token, address indexed oldGateway, address indexed newGateway)
event SetERC20Gateway(address indexed token, address indexed gateway)
```
Emitted when the `gateway` for `token` is updated.
@@ -502,13 +501,12 @@ Emitted when the `gateway` for `token` is updated.
| Name | Type | Description |
|---|---|---|
| token `indexed` | address | undefined |
| oldGateway `indexed` | address | undefined |
| newGateway `indexed` | address | undefined |
| gateway `indexed` | address | undefined |
### SetETHGateway
```solidity
event SetETHGateway(address indexed oldETHGateway, address indexed newEthGateway)
event SetETHGateway(address indexed ethGateway)
```
Emitted when the address of ETH Gateway is updated.
@@ -519,8 +517,7 @@ Emitted when the address of ETH Gateway is updated.
| Name | Type | Description |
|---|---|---|
| oldETHGateway `indexed` | address | undefined |
| newEthGateway `indexed` | address | undefined |
| ethGateway `indexed` | address | undefined |
### WithdrawERC20

View File

@@ -47,7 +47,7 @@ The address of fee vault, collecting cross domain messaging fee.
### initialize
```solidity
function initialize(address _counterpart) external nonpayable
function initialize(address _counterpart, address _feeVault) external nonpayable
```
@@ -59,6 +59,7 @@ function initialize(address _counterpart) external nonpayable
| Name | Type | Description |
|---|---|---|
| _counterpart | address | undefined |
| _feeVault | address | undefined |
### isL1MessageExecuted
@@ -315,7 +316,7 @@ Update fee vault contract.
### updateMaxFailedExecutionTimes
```solidity
function updateMaxFailedExecutionTimes(uint256 _newMaxFailedExecutionTimes) external nonpayable
function updateMaxFailedExecutionTimes(uint256 _maxFailedExecutionTimes) external nonpayable
```
Update max failed execution times.
@@ -326,7 +327,7 @@ Update max failed execution times.
| Name | Type | Description |
|---|---|---|
| _newMaxFailedExecutionTimes | uint256 | The new max failed execution times. |
| _maxFailedExecutionTimes | uint256 | The new max failed execution times. |
### xDomainMessageSender
@@ -487,7 +488,7 @@ Emitted when owner updates fee vault contract.
### UpdateMaxFailedExecutionTimes
```solidity
event UpdateMaxFailedExecutionTimes(uint256 oldMaxFailedExecutionTimes, uint256 newMaxFailedExecutionTimes)
event UpdateMaxFailedExecutionTimes(uint256 maxFailedExecutionTimes)
```
Emitted when the maximum number of times each message can fail in L2 is updated.
@@ -498,8 +499,7 @@ Emitted when the maximum number of times each message can fail in L2 is updated.
| Name | Type | Description |
|---|---|---|
| oldMaxFailedExecutionTimes | uint256 | undefined |
| newMaxFailedExecutionTimes | uint256 | undefined |
| maxFailedExecutionTimes | uint256 | The new maximum number of times each message can fail in L2. |

View File

@@ -128,34 +128,6 @@ The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
|---|---|---|
| _0 | address | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
@@ -190,22 +162,6 @@ The address of ScrollStandardERC20Factory.
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### withdrawERC20
```solidity
@@ -304,23 +260,6 @@ event Initialized(uint8 version)
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### WithdrawERC20
```solidity

View File

@@ -161,34 +161,6 @@ The address of corresponding L1ScrollMessenger/L2ScrollMessenger contract.
|---|---|---|
| _0 | address | undefined |
### owner
```solidity
function owner() external view returns (address)
```
*Returns the address of the current owner.*
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### renounceOwnership
```solidity
function renounceOwnership() external nonpayable
```
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### router
```solidity
@@ -206,22 +178,6 @@ The address of L1GatewayRouter/L2GatewayRouter contract.
|---|---|---|
| _0 | address | undefined |
### transferOwnership
```solidity
function transferOwnership(address newOwner) external nonpayable
```
*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*
#### Parameters
| Name | Type | Description |
|---|---|---|
| newOwner | address | undefined |
### withdrawERC20
```solidity
@@ -320,23 +276,6 @@ event Initialized(uint8 version)
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| previousOwner `indexed` | address | undefined |
| newOwner `indexed` | address | undefined |
### WithdrawERC20
```solidity

View File

@@ -60,10 +60,14 @@ const config: HardhatUserConfig = {
},
l1geth: {
url: SCROLL_L1_RPC,
gasPrice: 20000000000,
gasMultiplier: 1.1,
accounts: [L1_DEPLOYER_PRIVATE_KEY],
},
l2geth: {
url: SCROLL_L2_RPC,
gasPrice: 20000000000,
gasMultiplier: 1.1,
accounts: [L2_DEPLOYER_PRIVATE_KEY],
},
},
@@ -79,16 +83,6 @@ const config: HardhatUserConfig = {
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
customChains: [
{
network: "l2geth",
chainId: 534351,
urls: {
apiURL: "https://sepolia-blockscout.scroll.io/api",
browserURL: "https://sepolia-blockscout.scroll.io",
},
},
],
},
dodoc: {
runOnCompile: true,

View File

@@ -1,6 +1,7 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { constants } from "ethers";
import { concat } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { ScrollChain, L1MessageQueue } from "../typechain";
@@ -27,7 +28,7 @@ describe("ScrollChain", async () => {
await chain.deployed();
await chain.initialize(queue.address, constants.AddressZero, 44);
await chain.addSequencer(deployer.address);
await chain.updateSequencer(deployer.address, true);
await queue.initialize(
constants.AddressZero,
chain.address,

View File

@@ -21,7 +21,7 @@ async function main() {
if (!addressFile.get(`${contractName}.implementation`)) {
console.log(`>> Deploy ${contractName} implementation`);
const ContractImpl = await ethers.getContractFactory(contractName, deployer);
const impl = await ContractImpl.deploy(process.env.L1_USDC_ADDR, process.env.L2_USDC_ADDR);
const impl = await ContractImpl.deploy();
console.log(`>> waiting for transaction: ${impl.deployTransaction.hash}`);
await impl.deployed();
console.log(`${contractName} implementation deployed at ${impl.address}`);

View File

@@ -22,7 +22,6 @@ contract InitializeL1BridgeContracts is Script {
uint256 CHAIN_ID_L2 = vm.envUint("CHAIN_ID_L2");
uint256 MAX_L2_TX_IN_CHUNK = vm.envUint("MAX_L2_TX_IN_CHUNK");
uint256 MAX_L1_MESSAGE_GAS_LIMIT = vm.envUint("MAX_L1_MESSAGE_GAS_LIMIT");
address L1_ROLLUP_OPERATOR_ADDR = vm.envAddress("L1_ROLLUP_OPERATOR_ADDR");
address L1_FEE_VAULT_ADDR = vm.envAddress("L1_FEE_VAULT_ADDR");
address L1_WETH_ADDR = vm.envAddress("L1_WETH_ADDR");
@@ -67,8 +66,8 @@ contract InitializeL1BridgeContracts is Script {
L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR,
MAX_L2_TX_IN_CHUNK
);
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addSequencer(L1_ROLLUP_OPERATOR_ADDR);
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).addProver(L1_ROLLUP_OPERATOR_ADDR);
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).updateSequencer(L1_ROLLUP_OPERATOR_ADDR, true);
ScrollChain(L1_SCROLL_CHAIN_PROXY_ADDR).updateProver(L1_ROLLUP_OPERATOR_ADDR, true);
// initialize L2GasPriceOracle
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).initialize(
@@ -85,7 +84,7 @@ contract InitializeL1BridgeContracts is Script {
L1_SCROLL_CHAIN_PROXY_ADDR,
L1_ENFORCED_TX_GATEWAY_PROXY_ADDR,
L2_GAS_PRICE_ORACLE_PROXY_ADDR,
MAX_L1_MESSAGE_GAS_LIMIT
10000000
);
// initialize L1ScrollMessenger

View File

@@ -65,7 +65,10 @@ contract InitializeL2BridgeContracts is Script {
L1GasPriceOracle(L1_GAS_PRICE_ORACLE_ADDR).updateWhitelist(L2_WHITELIST_ADDR);
// initialize L2ScrollMessenger
L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).initialize(L1_SCROLL_MESSENGER_PROXY_ADDR);
L2ScrollMessenger(payable(L2_SCROLL_MESSENGER_PROXY_ADDR)).initialize(
L1_SCROLL_MESSENGER_PROXY_ADDR,
L2_TX_FEE_VAULT_ADDR
);
// initialize L2GatewayRouter
L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).initialize(

View File

@@ -25,18 +25,18 @@ async function main() {
const L2StandardERC20Impl = process.env.L2_SCROLL_STANDARD_ERC20_ADDR!;
const L2StandardERC20FactoryAddress = process.env.L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR!;
if ((await L1StandardERC20Gateway.counterpart()) === constants.AddressZero) {
const tx = await L1StandardERC20Gateway.initialize(
L2StandardERC20GatewayAddress,
L1GatewayRouterAddress,
L1ScrollMessengerAddress,
L2StandardERC20Impl,
L2StandardERC20FactoryAddress
);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
// if ((await L1StandardERC20Gateway.counterpart()) === constants.AddressZero) {
const tx = await L1StandardERC20Gateway.initialize(
L2StandardERC20GatewayAddress,
L1GatewayRouterAddress,
L1ScrollMessengerAddress,
L2StandardERC20Impl,
L2StandardERC20FactoryAddress
);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
// }
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -23,16 +23,16 @@ async function main() {
const L1ScrollMessengerAddress = addressFile.get("L1ScrollMessenger.proxy");
const L2GatewayRouterAddress = process.env.L2_GATEWAY_ROUTER_PROXY_ADDR!;
if ((await L1GatewayRouter.counterpart()) === constants.AddressZero) {
const tx = await L1GatewayRouter.initialize(
L1StandardERC20GatewayAddress,
L2GatewayRouterAddress,
L1ScrollMessengerAddress
);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
// if ((await L1GatewayRouter.counterpart()) === constants.AddressZero) {
const tx = await L1GatewayRouter.initialize(
L1StandardERC20GatewayAddress,
L2GatewayRouterAddress,
L1ScrollMessengerAddress
);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
// }
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -21,12 +21,12 @@ async function main() {
const ZKRollupAddress = addressFile.get("ZKRollup.proxy");
if ((await L1ScrollMessenger.rollup()) === constants.AddressZero) {
const tx = await L1ScrollMessenger.initialize(ZKRollupAddress);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
// if ((await L1ScrollMessenger.rollup()) === constants.AddressZero) {
const tx = await L1ScrollMessenger.initialize(ZKRollupAddress);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
// }
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -1,35 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as dotenv from "dotenv";
import { constants } from "ethers";
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
dotenv.config();
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const L1USDCGateway = await ethers.getContractAt("L1USDCGateway", addressFile.get("L1USDCGateway.proxy"), deployer);
const L1GatewayRouterAddress = addressFile.get("L1GatewayRouter.proxy");
const L1ScrollMessengerAddress = addressFile.get("L1ScrollMessenger.proxy");
const L2USDCGatewayAddress = process.env.L2_USDC_GATEWAY_PROXY_ADDR!;
if ((await L1USDCGateway.counterpart()) === constants.AddressZero) {
const tx = await L1USDCGateway.initialize(L2USDCGatewayAddress, L1GatewayRouterAddress, L1ScrollMessengerAddress);
console.log("initialize L1USDCGateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

View File

@@ -24,17 +24,17 @@ async function main() {
const L2StandardERC20FactoryAddress = addressFile.get("ScrollStandardERC20Factory");
const L1StandardERC20GatewayAddress = process.env.L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR!;
if ((await L2StandardERC20Gateway.counterpart()) === constants.AddressZero) {
const tx = await L2StandardERC20Gateway.initialize(
L1StandardERC20GatewayAddress,
L2GatewayRouterAddress,
L2ScrollMessengerAddress,
L2StandardERC20FactoryAddress
);
console.log("initialize L2StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
// if ((await L2StandardERC20Gateway.counterpart()) === constants.AddressZero) {
const tx = await L2StandardERC20Gateway.initialize(
L1StandardERC20GatewayAddress,
L2GatewayRouterAddress,
L2ScrollMessengerAddress,
L2StandardERC20FactoryAddress
);
console.log("initialize L2StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
// }
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -23,16 +23,16 @@ async function main() {
const L2ScrollMessengerAddress = addressFile.get("L2ScrollMessenger");
const L1GatewayRouterAddress = process.env.L1_GATEWAY_ROUTER_PROXY_ADDR!;
if ((await L2GatewayRouter.counterpart()) === constants.AddressZero) {
const tx = await L2GatewayRouter.initialize(
L2StandardERC20GatewayAddress,
L1GatewayRouterAddress,
L2ScrollMessengerAddress
);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
// if ((await L2GatewayRouter.counterpart()) === constants.AddressZero) {
const tx = await L2GatewayRouter.initialize(
L2StandardERC20GatewayAddress,
L1GatewayRouterAddress,
L2ScrollMessengerAddress
);
console.log("initialize L1StandardERC20Gateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
// }
}
// We recommend this pattern to be able to use async/await everywhere

View File

@@ -1,35 +0,0 @@
/* eslint-disable node/no-missing-import */
import * as dotenv from "dotenv";
import { constants } from "ethers";
import * as hre from "hardhat";
import { ethers } from "hardhat";
import { selectAddressFile } from "./utils";
dotenv.config();
async function main() {
const addressFile = selectAddressFile(hre.network.name);
const [deployer] = await ethers.getSigners();
const L2USDCGateway = await ethers.getContractAt("L2USDCGateway", addressFile.get("L2USDCGateway.proxy"), deployer);
const L2GatewayRouterAddress = addressFile.get("L2GatewayRouter.proxy");
const L2ScrollMessengerAddress = addressFile.get("L2ScrollMessenger.proxy");
const L1USDCGatewayAddress = process.env.L1_USDC_GATEWAY_PROXY_ADDR!;
if ((await L2USDCGateway.counterpart()) === constants.AddressZero) {
const tx = await L2USDCGateway.initialize(L1USDCGatewayAddress, L2GatewayRouterAddress, L2ScrollMessengerAddress);
console.log("initialize L2USDCGateway, hash:", tx.hash);
const receipt = await tx.wait();
console.log(`✅ Done, gas used: ${receipt.gasUsed}`);
}
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});

View File

@@ -10,9 +10,8 @@ interface IL1ScrollMessenger is IScrollMessenger {
**********/
/// @notice Emitted when the maximum number of times each message can be replayed is updated.
/// @param oldMaxReplayTimes The old maximum number of times each message can be replayed.
/// @param newMaxReplayTimes The new maximum number of times each message can be replayed.
event UpdateMaxReplayTimes(uint256 oldMaxReplayTimes, uint256 newMaxReplayTimes);
/// @param maxReplayTimes The new maximum number of times each message can be replayed.
event UpdateMaxReplayTimes(uint256 maxReplayTimes);
/***********
* Structs *

View File

@@ -2,12 +2,15 @@
pragma solidity =0.8.16;
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {IScrollChain} from "./rollup/IScrollChain.sol";
import {IL1MessageQueue} from "./rollup/IL1MessageQueue.sol";
import {IL1ScrollMessenger} from "./IL1ScrollMessenger.sol";
import {ScrollConstants} from "../libraries/constants/ScrollConstants.sol";
import {IScrollMessenger} from "../libraries/IScrollMessenger.sol";
import {ScrollMessengerBase} from "../libraries/ScrollMessengerBase.sol";
import {AddressAliasHelper} from "../libraries/common/AddressAliasHelper.sol";
import {WithdrawTrieVerifier} from "../libraries/verifier/WithdrawTrieVerifier.sol";
import {IMessageDropCallback} from "../libraries/callbacks/IMessageDropCallback.sol";
@@ -25,7 +28,7 @@ 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 {
contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1ScrollMessenger {
/***********
* Structs *
***********/
@@ -94,7 +97,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
address _rollup,
address _messageQueue
) public initializer {
ScrollMessengerBase.__ScrollMessengerBase_init(_counterpart, _feeVault);
PausableUpgradeable.__Pausable_init();
ScrollMessengerBase._initialize(_counterpart, _feeVault);
rollup = _rollup;
messageQueue = _messageQueue;
@@ -291,14 +295,24 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
* Restricted Functions *
************************/
/// @notice Pause the contract
/// @dev This function can only called by contract owner.
/// @param _status The pause status to update.
function setPause(bool _status) external onlyOwner {
if (_status) {
_pause();
} else {
_unpause();
}
}
/// @notice Update max replay times.
/// @dev This function can only called by contract owner.
/// @param _newMaxReplayTimes The new max replay times.
function updateMaxReplayTimes(uint256 _newMaxReplayTimes) external onlyOwner {
uint256 _oldMaxReplayTimes = maxReplayTimes;
maxReplayTimes = _newMaxReplayTimes;
/// @param _maxReplayTimes The new max replay times.
function updateMaxReplayTimes(uint256 _maxReplayTimes) external onlyOwner {
maxReplayTimes = _maxReplayTimes;
emit UpdateMaxReplayTimes(_oldMaxReplayTimes, _newMaxReplayTimes);
emit UpdateMaxReplayTimes(_maxReplayTimes);
}
/**********************

View File

@@ -11,20 +11,17 @@ interface IL1GatewayRouter is IL1ETHGateway, IL1ERC20Gateway {
**********/
/// @notice Emitted when the address of ETH Gateway is updated.
/// @param oldETHGateway The address of the old ETH Gateway.
/// @param newEthGateway The address of the new ETH Gateway.
event SetETHGateway(address indexed oldETHGateway, address indexed newEthGateway);
/// @param ethGateway The address of new ETH Gateway.
event SetETHGateway(address indexed ethGateway);
/// @notice Emitted when the address of default ERC20 Gateway is updated.
/// @param oldDefaultERC20Gateway The address of the old default ERC20 Gateway.
/// @param newDefaultERC20Gateway The address of the new default ERC20 Gateway.
event SetDefaultERC20Gateway(address indexed oldDefaultERC20Gateway, address indexed newDefaultERC20Gateway);
/// @param defaultERC20Gateway The address of new default ERC20 Gateway.
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway);
/// @notice Emitted when the `gateway` for `token` is updated.
/// @param token The address of token updated.
/// @param oldGateway The corresponding address of the old gateway.
/// @param newGateway The corresponding address of the new gateway.
event SetERC20Gateway(address indexed token, address indexed oldGateway, address indexed newGateway);
/// @param gateway The corresponding address of gateway updated.
event SetERC20Gateway(address indexed token, address indexed gateway);
/*************************
* Public View Functions *

View File

@@ -2,6 +2,7 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
@@ -17,7 +18,7 @@ import {L1ERC20Gateway} from "./L1ERC20Gateway.sol";
/// finalize withdraw the tokens from layer 2.
/// @dev The deposited tokens are held in this gateway. On finalizing withdraw, the corresponding
/// tokens will be transfer to the recipient directly.
contract L1CustomERC20Gateway is L1ERC20Gateway {
contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20Gateway {
using SafeERC20Upgradeable for IERC20Upgradeable;
/**********
@@ -25,10 +26,9 @@ contract L1CustomERC20Gateway is L1ERC20Gateway {
**********/
/// @notice Emitted when token mapping for ERC20 token is updated.
/// @param l1Token The address of ERC20 token in layer 1.
/// @param oldL2Token The address of the old corresponding ERC20 token in layer 2.
/// @param newL2Token The address of the new corresponding ERC20 token in layer 2.
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token);
/// @param _l1Token The address of ERC20 token on layer 1.
/// @param _l2Token The address of corresponding ERC20 token on layer 2.
event UpdateTokenMapping(address _l1Token, address _l2Token);
/*************
* Variables *
@@ -56,6 +56,7 @@ contract L1CustomERC20Gateway is L1ERC20Gateway {
) external initializer {
require(_router != address(0), "zero router address");
OwnableUpgradeable.__Ownable_init();
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
}
@@ -78,10 +79,9 @@ contract L1CustomERC20Gateway is L1ERC20Gateway {
function updateTokenMapping(address _l1Token, address _l2Token) external onlyOwner {
require(_l2Token != address(0), "token address cannot be 0");
address _oldL2Token = tokenMapping[_l1Token];
tokenMapping[_l1Token] = _l2Token;
emit UpdateTokenMapping(_l1Token, _oldL2Token, _l2Token);
emit UpdateTokenMapping(_l1Token, _l2Token);
}
/**********************

View File

@@ -2,6 +2,7 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
import {ERC1155HolderUpgradeable, ERC1155ReceiverUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155HolderUpgradeable.sol";
@@ -19,16 +20,21 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// NFT will be transfer to the recipient directly.
///
/// This will be changed if we have more specific scenarios.
contract L1ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL1ERC1155Gateway, IMessageDropCallback {
contract L1ERC1155Gateway is
OwnableUpgradeable,
ERC1155HolderUpgradeable,
ScrollGatewayBase,
IL1ERC1155Gateway,
IMessageDropCallback
{
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC1155 token is updated.
/// @param l1Token The address of ERC1155 token in layer 1.
/// @param oldL2Token The address of the old corresponding ERC1155 token in layer 2.
/// @param newL2Token The address of the new corresponding ERC1155 token in layer 2.
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token);
/// @param _l1Token The address of ERC1155 token on layer 1.
/// @param _l2Token The address of corresponding ERC1155 token on layer 2.
event UpdateTokenMapping(address _l1Token, address _l2Token);
/*************
* Variables *
@@ -49,6 +55,7 @@ contract L1ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL1ERC
/// @param _counterpart The address of L2ERC1155Gateway in L2.
/// @param _messenger The address of L1ScrollMessenger.
function initialize(address _counterpart, address _messenger) external initializer {
OwnableUpgradeable.__Ownable_init();
ERC1155HolderUpgradeable.__ERC1155Holder_init();
ERC1155ReceiverUpgradeable.__ERC1155Receiver_init();
@@ -170,10 +177,9 @@ contract L1ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL1ERC
function updateTokenMapping(address _l1Token, address _l2Token) external onlyOwner {
require(_l2Token != address(0), "token address cannot be 0");
address _oldL2Token = tokenMapping[_l1Token];
tokenMapping[_l1Token] = _l2Token;
emit UpdateTokenMapping(_l1Token, _oldL2Token, _l2Token);
emit UpdateTokenMapping(_l1Token, _l2Token);
}
/**********************

View File

@@ -2,12 +2,14 @@
pragma solidity ^0.8.16;
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IL1ERC20Gateway} from "./IL1ERC20Gateway.sol";
import {IL1GatewayRouter} from "./IL1GatewayRouter.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {IL2ERC20Gateway} from "../../L2/gateways/IL2ERC20Gateway.sol";
import {IScrollMessenger} from "../../libraries/IScrollMessenger.sol";
import {ScrollConstants} from "../../libraries/constants/ScrollConstants.sol";
@@ -17,7 +19,7 @@ import {IMessageDropCallback} from "../../libraries/callbacks/IMessageDropCallba
// solhint-disable no-empty-blocks
abstract contract L1ERC20Gateway is IL1ERC20Gateway, IMessageDropCallback, ScrollGatewayBase {
using SafeERC20Upgradeable for IERC20Upgradeable;
using SafeERC20 for IERC20;
/*************
* Variables *
@@ -68,12 +70,12 @@ abstract contract L1ERC20Gateway is IL1ERC20Gateway, IMessageDropCallback, Scrol
address _to,
uint256 _amount,
bytes calldata _data
) external payable virtual override onlyCallByCounterpart nonReentrant {
) external payable override onlyCallByCounterpart nonReentrant {
_beforeFinalizeWithdrawERC20(_l1Token, _l2Token, _from, _to, _amount, _data);
// @note can possible trigger reentrant call to this contract or messenger,
// but it seems not a big problem.
IERC20Upgradeable(_l1Token).safeTransfer(_to, _amount);
IERC20(_l1Token).safeTransfer(_to, _amount);
_doCallback(_to, _data);
@@ -94,7 +96,7 @@ abstract contract L1ERC20Gateway is IL1ERC20Gateway, IMessageDropCallback, Scrol
// do dome check for each custom gateway
_beforeDropMessage(_token, _receiver, _amount);
IERC20Upgradeable(_token).safeTransfer(_receiver, _amount);
IERC20(_token).safeTransfer(_receiver, _amount);
emit RefundERC20(_token, _receiver, _amount);
}
@@ -152,9 +154,9 @@ abstract contract L1ERC20Gateway is IL1ERC20Gateway, IMessageDropCallback, Scrol
_amount = IL1GatewayRouter(msg.sender).requestERC20(_from, _token, _amount);
} else {
// common practice to handle fee on transfer token.
uint256 _before = IERC20Upgradeable(_token).balanceOf(address(this));
IERC20Upgradeable(_token).safeTransferFrom(_from, address(this), _amount);
uint256 _after = IERC20Upgradeable(_token).balanceOf(address(this));
uint256 _before = IERC20(_token).balanceOf(address(this));
IERC20(_token).safeTransferFrom(_from, address(this), _amount);
uint256 _after = IERC20(_token).balanceOf(address(this));
// no unchecked here, since some weird token may return arbitrary balance.
_amount = _after - _before;
}

View File

@@ -2,6 +2,7 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import {ERC721HolderUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol";
@@ -19,16 +20,21 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// NFT will be transfer to the recipient directly.
///
/// This will be changed if we have more specific scenarios.
contract L1ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL1ERC721Gateway, IMessageDropCallback {
contract L1ERC721Gateway is
OwnableUpgradeable,
ERC721HolderUpgradeable,
ScrollGatewayBase,
IL1ERC721Gateway,
IMessageDropCallback
{
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC721 token is updated.
/// @param l1Token The address of ERC721 token in layer 1.
/// @param oldL2Token The address of the old corresponding ERC721 token in layer 2.
/// @param newL2Token The address of the new corresponding ERC721 token in layer 2.
event UpdateTokenMapping(address indexed l1Token, address indexed oldL2Token, address indexed newL2Token);
/// @param _l1Token The address of ERC721 token on layer 1.
/// @param _l2Token The address of corresponding ERC721 token on layer 2.
event UpdateTokenMapping(address _l1Token, address _l2Token);
/*************
* Variables *
@@ -49,6 +55,7 @@ contract L1ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL1ERC72
/// @param _counterpart The address of L2ERC721Gateway in L2.
/// @param _messenger The address of L1ScrollMessenger.
function initialize(address _counterpart, address _messenger) external initializer {
OwnableUpgradeable.__Ownable_init();
ERC721HolderUpgradeable.__ERC721Holder_init();
ScrollGatewayBase._initialize(_counterpart, address(0), _messenger);
@@ -166,10 +173,9 @@ contract L1ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL1ERC72
function updateTokenMapping(address _l1Token, address _l2Token) external onlyOwner {
require(_l2Token != address(0), "token address cannot be 0");
address _oldL2Token = tokenMapping[_l1Token];
tokenMapping[_l1Token] = _l2Token;
emit UpdateTokenMapping(_l1Token, _oldL2Token, _l2Token);
emit UpdateTokenMapping(_l1Token, _l2Token);
}
/**********************

View File

@@ -2,6 +2,8 @@
pragma solidity =0.8.16;
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IL2ETHGateway} from "../../L2/gateways/IL2ETHGateway.sol";
import {IL1ScrollMessenger} from "../IL1ScrollMessenger.sol";
import {IL1ETHGateway} from "./IL1ETHGateway.sol";
@@ -16,7 +18,7 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// finalize withdraw ETH from layer 2.
/// @dev The deposited ETH tokens are held in this gateway. On finalizing withdraw, the corresponding
/// ETH will be transfer to the recipient directly.
contract L1ETHGateway is ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback {
contract L1ETHGateway is Initializable, ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback {
/***************
* Constructor *
***************/

View File

@@ -6,6 +6,8 @@ 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 {IScrollGateway} from "../../libraries/gateway/IScrollGateway.sol";
import {IL1ScrollMessenger} from "../IL1ScrollMessenger.sol";
import {IL1ETHGateway} from "./IL1ETHGateway.sol";
import {IL1ERC20Gateway} from "./IL1ERC20Gateway.sol";
import {IL1GatewayRouter} from "./IL1GatewayRouter.sol";
@@ -66,13 +68,13 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
// it can be zero during initialization
if (_defaultERC20Gateway != address(0)) {
defaultERC20Gateway = _defaultERC20Gateway;
emit SetDefaultERC20Gateway(address(0), _defaultERC20Gateway);
emit SetDefaultERC20Gateway(_defaultERC20Gateway);
}
// it can be zero during initialization
if (_ethGateway != address(0)) {
ethGateway = _ethGateway;
emit SetETHGateway(address(0), _ethGateway);
emit SetETHGateway(_ethGateway);
}
}
@@ -223,19 +225,17 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
************************/
/// @inheritdoc IL1GatewayRouter
function setETHGateway(address _newEthGateway) external onlyOwner {
address _oldETHGateway = ethGateway;
ethGateway = _newEthGateway;
function setETHGateway(address _ethGateway) external onlyOwner {
ethGateway = _ethGateway;
emit SetETHGateway(_oldETHGateway, _newEthGateway);
emit SetETHGateway(_ethGateway);
}
/// @inheritdoc IL1GatewayRouter
function setDefaultERC20Gateway(address _newDefaultERC20Gateway) external onlyOwner {
address _oldDefaultERC20Gateway = defaultERC20Gateway;
defaultERC20Gateway = _newDefaultERC20Gateway;
function setDefaultERC20Gateway(address _defaultERC20Gateway) external onlyOwner {
defaultERC20Gateway = _defaultERC20Gateway;
emit SetDefaultERC20Gateway(_oldDefaultERC20Gateway, _newDefaultERC20Gateway);
emit SetDefaultERC20Gateway(_defaultERC20Gateway);
}
/// @inheritdoc IL1GatewayRouter
@@ -243,10 +243,9 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
require(_tokens.length == _gateways.length, "length mismatch");
for (uint256 i = 0; i < _tokens.length; i++) {
address _oldGateway = ERC20Gateway[_tokens[i]];
ERC20Gateway[_tokens[i]] = _gateways[i];
emit SetERC20Gateway(_tokens[i], _oldGateway, _gateways[i]);
emit SetERC20Gateway(_tokens[i], _gateways[i]);
}
}
}

View File

@@ -2,9 +2,12 @@
pragma solidity =0.8.16;
import {ClonesUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/ClonesUpgradeable.sol";
import {IERC20MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {IERC20Metadata} from "../../interfaces/IERC20Metadata.sol";
import {IL2ERC20Gateway} from "../../L2/gateways/IL2ERC20Gateway.sol";
import {IL1ScrollMessenger} from "../IL1ScrollMessenger.sol";
import {IL1ERC20Gateway} from "./IL1ERC20Gateway.sol";
@@ -18,7 +21,9 @@ import {L1ERC20Gateway} from "./L1ERC20Gateway.sol";
/// @dev The deposited ERC20 tokens are held in this gateway. On finalizing withdraw, the corresponding
/// token will be transfer to the recipient directly. Any ERC20 that requires non-standard functionality
/// should use a separate gateway.
contract L1StandardERC20Gateway is L1ERC20Gateway {
contract L1StandardERC20Gateway is Initializable, ScrollGatewayBase, L1ERC20Gateway {
using SafeERC20 for IERC20;
/*************
* Variables *
*************/
@@ -76,7 +81,7 @@ contract L1StandardERC20Gateway is L1ERC20Gateway {
// we can calculate the l2 address directly.
bytes32 _salt = keccak256(abi.encodePacked(counterpart, keccak256(abi.encodePacked(_l1Token))));
return ClonesUpgradeable.predictDeterministicAddress(l2TokenImplementation, _salt, l2TokenFactory);
return Clones.predictDeterministicAddress(l2TokenImplementation, _salt, l2TokenFactory);
}
/**********************
@@ -138,9 +143,9 @@ contract L1StandardERC20Gateway is L1ERC20Gateway {
_l2Token = getL2ERC20Address(_token);
// passing symbol/name/decimal in order to deploy in L2.
string memory _symbol = IERC20MetadataUpgradeable(_token).symbol();
string memory _name = IERC20MetadataUpgradeable(_token).name();
uint8 _decimals = IERC20MetadataUpgradeable(_token).decimals();
string memory _symbol = IERC20Metadata(_token).symbol();
string memory _name = IERC20Metadata(_token).name();
uint8 _decimals = IERC20Metadata(_token).decimals();
_l2Data = abi.encode(true, abi.encode(_data, abi.encode(_symbol, _name, _decimals)));
} else {
_l2Data = abi.encode(false, _data);

View File

@@ -2,6 +2,10 @@
pragma solidity =0.8.16;
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IWETH} from "../../interfaces/IWETH.sol";
import {IL2ERC20Gateway} from "../../L2/gateways/IL2ERC20Gateway.sol";
import {IL1ScrollMessenger} from "../IL1ScrollMessenger.sol";
@@ -17,7 +21,9 @@ import {L1ERC20Gateway} from "./L1ERC20Gateway.sol";
/// as Ether and then the Ether will be sent to the `L1ScrollMessenger` contract.
/// On finalizing withdraw, the Ether will be transfered from `L1ScrollMessenger`, then
/// wrapped as WETH and finally transfer to recipient.
contract L1WETHGateway is L1ERC20Gateway {
contract L1WETHGateway is Initializable, ScrollGatewayBase, L1ERC20Gateway {
using SafeERC20 for IERC20;
/*************
* Constants *
*************/

View File

@@ -2,163 +2,10 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {L1CustomERC20Gateway} from "../L1CustomERC20Gateway.sol";
import {IFiatToken} from "../../../interfaces/IFiatToken.sol";
import {IUSDCBurnableSourceBridge} from "../../../interfaces/IUSDCBurnableSourceBridge.sol";
import {IL2ERC20Gateway} from "../../../L2/gateways/IL2ERC20Gateway.sol";
import {IL1ScrollMessenger} from "../../IL1ScrollMessenger.sol";
import {IL1ERC20Gateway} from "../IL1ERC20Gateway.sol";
// solhint-disable no-empty-blocks
import {ScrollGatewayBase} from "../../../libraries/gateway/ScrollGatewayBase.sol";
import {L1ERC20Gateway} from "../L1ERC20Gateway.sol";
contract L1USDCGateway is L1CustomERC20Gateway {
/// @title L1USDCGateway
/// @notice The `L1USDCGateway` contract is used to deposit `USDC` token in layer 1 and
/// finalize withdraw `USDC` from layer 2, before USDC become native in layer 2.
contract L1USDCGateway is L1ERC20Gateway, IUSDCBurnableSourceBridge {
using SafeERC20Upgradeable for IERC20Upgradeable;
/*************
* Constants *
*************/
/// @notice The address of L1 USDC address.
// solhint-disable-next-line var-name-mixedcase
address public immutable l1USDC;
/// @notice The address of L2 USDC address.
address public immutable l2USDC;
/*************
* Variables *
*************/
address public circleCaller;
bool public depositPaused;
bool public withdrawPaused;
/***************
* Constructor *
***************/
constructor(address _l1USDC, address _l2USDC) {
_disableInitializers();
l1USDC = _l1USDC;
l2USDC = _l2USDC;
}
/// @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(
address _counterpart,
address _router,
address _messenger
) external initializer {
require(_router != address(0), "zero router address");
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
}
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IL1ERC20Gateway
function getL2ERC20Address(address) public view override returns (address) {
return l2USDC;
}
/*******************************
* Public Restricted Functions *
*******************************/
/// @inheritdoc IUSDCBurnableSourceBridge
function burnAllLockedUSDC() external override {
require(msg.sender == circleCaller, "only circle caller");
uint256 _balance = IERC20Upgradeable(l1USDC).balanceOf(address(this));
require(IFiatToken(l1USDC).burn(_balance), "burn USDC failed");
}
/// @notice Update the Circle EOA address.
/// @param _caller The address to update.
function updateCircleCaller(address _caller) external onlyOwner {
circleCaller = _caller;
}
/// @notice Change the deposit pause status of this contract.
/// @param _paused The new status, `true` means paused and `false` means not paused.
function pauseDeposit(bool _paused) external onlyOwner {
depositPaused = _paused;
}
/// @notice Change the withdraw pause status of this contract.
/// @param _paused The new status, `true` means paused and `false` means not paused.
function pauseWithdraw(bool _paused) external onlyOwner {
withdrawPaused = _paused;
}
/**********************
* Internal Functions *
**********************/
/// @inheritdoc L1ERC20Gateway
function _beforeFinalizeWithdrawERC20(
address _l1Token,
address _l2Token,
address,
address,
uint256,
bytes calldata
) internal virtual override {
require(msg.value == 0, "nonzero msg.value");
require(_l1Token == l1USDC, "l1 token not USDC");
require(_l2Token == l2USDC, "l2 token not USDC");
require(!withdrawPaused, "withdraw paused");
}
/// @inheritdoc L1ERC20Gateway
function _beforeDropMessage(
address,
address,
uint256
) internal virtual override {
require(msg.value == 0, "nonzero msg.value");
}
/// @inheritdoc L1ERC20Gateway
function _deposit(
address _token,
address _to,
uint256 _amount,
bytes memory _data,
uint256 _gasLimit
) internal virtual override nonReentrant {
require(_amount > 0, "deposit zero amount");
require(_token == l1USDC, "only USDC is allowed");
require(!depositPaused, "deposit paused");
// 1. Transfer token into this contract.
address _from;
(_from, _amount, _data) = _transferERC20In(_token, _amount, _data);
require(_data.length == 0, "call is not allowed");
// 2. Generate message passed to L2USDCGateway.
bytes memory _message = abi.encodeCall(
IL2ERC20Gateway.finalizeDepositERC20,
(_token, l2USDC, _from, _to, _amount, _data)
);
// 3. Send message to L1ScrollMessenger.
IL1ScrollMessenger(messenger).sendMessage{value: msg.value}(counterpart, 0, _message, _gasLimit, _from);
emit DepositERC20(_token, l2USDC, _from, _to, _amount, _data);
}
}

View File

@@ -1,184 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {ITokenMessenger} from "../../../interfaces/ITokenMessenger.sol";
import {IL2ERC20Gateway} from "../../../L2/gateways/IL2ERC20Gateway.sol";
import {IL1ScrollMessenger} from "../../IL1ScrollMessenger.sol";
import {IL1ERC20Gateway} from "../IL1ERC20Gateway.sol";
import {CCTPGatewayBase} from "../../../libraries/gateway/CCTPGatewayBase.sol";
import {ScrollGatewayBase} from "../../../libraries/gateway/ScrollGatewayBase.sol";
import {L1ERC20Gateway} from "../L1ERC20Gateway.sol";
/// @title L1USDCGatewayCCTP
/// @notice The `L1USDCGateway` contract is used to deposit `USDC` token in layer 1 and
/// finalize withdraw `USDC` from layer 2, after USDC become native in layer 2.
contract L1USDCGatewayCCTP is CCTPGatewayBase, L1ERC20Gateway {
using SafeERC20Upgradeable for IERC20Upgradeable;
/***************
* Constructor *
***************/
constructor(
address _l1USDC,
address _l2USDC,
uint32 _destinationDomain
) CCTPGatewayBase(_l1USDC, _l2USDC, _destinationDomain) {}
/// @notice Initialize the storage of L1USDCGatewayCCTP.
/// @param _counterpart The address of L2USDCGatewayCCTP in L2.
/// @param _router The address of L1GatewayRouter.
/// @param _messenger The address of L1ScrollMessenger.
/// @param _cctpMessenger The address of TokenMessenger in local domain.
/// @param _cctpTransmitter The address of MessageTransmitter in local domain.
function initialize(
address _counterpart,
address _router,
address _messenger,
address _cctpMessenger,
address _cctpTransmitter
) external initializer {
require(_router != address(0), "zero router address");
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
CCTPGatewayBase._initialize(_cctpMessenger, _cctpTransmitter);
OwnableUpgradeable.__Ownable_init();
}
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IL1ERC20Gateway
function getL2ERC20Address(address) public view override returns (address) {
return l2USDC;
}
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice Relay cross chain message and claim USDC that has been cross chained.
/// @dev The `_scrollMessage` is actually encoded calldata for `L1ScrollMessenger.relayMessageWithProof`.
///
/// @dev This helper function is aimed to claim USDC in single transaction.
/// Normally, an user should call `L1ScrollMessenger.relayMessageWithProof` first,
/// then `L1USDCGatewayCCTP.claimUSDC`.
///
/// @param _nonce The nonce of the message from CCTP.
/// @param _cctpMessage The message passed to MessageTransmitter contract in CCTP.
/// @param _cctpSignature The message passed to MessageTransmitter contract in CCTP.
/// @param _scrollMessage The message passed to L1ScrollMessenger contract.
function relayAndClaimUSDC(
uint256 _nonce,
bytes calldata _cctpMessage,
bytes calldata _cctpSignature,
bytes calldata _scrollMessage
) external {
require(status[_nonce] == CCTPMessageStatus.None, "message relayed");
// call messenger to set `status[_nonce]` to `CCTPMessageStatus.Pending`.
(bool _success, ) = messenger.call(_scrollMessage);
require(_success, "call messenger failed");
claimUSDC(_nonce, _cctpMessage, _cctpSignature);
}
/// @inheritdoc IL1ERC20Gateway
/// @dev The function will not mint the USDC, users need to call `claimUSDC` after this function is done.
function finalizeWithdrawERC20(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes memory _data
) external payable override onlyCallByCounterpart {
require(msg.value == 0, "nonzero msg.value");
require(_l1Token == l1USDC, "l1 token not USDC");
require(_l2Token == l2USDC, "l2 token not USDC");
uint256 _nonce;
(_nonce, _data) = abi.decode(_data, (uint256, bytes));
require(status[_nonce] == CCTPMessageStatus.None, "message relayed");
status[_nonce] = CCTPMessageStatus.Pending;
emit FinalizeWithdrawERC20(_l1Token, _l2Token, _from, _to, _amount, _data);
}
/*******************************
* Public Restricted Functions *
*******************************/
/// @notice Update the CCTP contract addresses.
/// @param _messenger The address of TokenMessenger in local domain.
/// @param _transmitter The address of MessageTransmitter in local domain.
function updateCCTPContracts(address _messenger, address _transmitter) external onlyOwner {
cctpMessenger = _messenger;
cctpTransmitter = _transmitter;
}
/**********************
* Internal Functions *
**********************/
/// @inheritdoc L1ERC20Gateway
function _beforeFinalizeWithdrawERC20(
address,
address,
address,
address,
uint256,
bytes calldata
) internal virtual override {}
/// @inheritdoc L1ERC20Gateway
function _beforeDropMessage(
address,
address,
uint256
) internal virtual override {
require(msg.value == 0, "nonzero msg.value");
}
/// @inheritdoc L1ERC20Gateway
function _deposit(
address _token,
address _to,
uint256 _amount,
bytes memory _data,
uint256 _gasLimit
) internal virtual override nonReentrant {
require(_amount > 0, "deposit zero amount");
require(_token == l1USDC, "only USDC is allowed");
// 1. Extract real sender if this call is from L1GatewayRouter.
address _from;
(_from, _amount, _data) = _transferERC20In(_token, _amount, _data);
// 2. Burn token through CCTP TokenMessenger
uint256 _nonce = ITokenMessenger(cctpMessenger).depositForBurnWithCaller(
_amount,
destinationDomain,
bytes32(uint256(uint160(_to))),
address(this),
bytes32(uint256(uint160(counterpart)))
);
// 3. Generate message passed to L2USDCGatewayCCTP.
bytes memory _message = abi.encodeCall(
IL2ERC20Gateway.finalizeDepositERC20,
(_token, l2USDC, _from, _to, _amount, abi.encode(_nonce, _data))
);
// 4. Send message to L1ScrollMessenger.
IL1ScrollMessenger(messenger).sendMessage{value: msg.value}(counterpart, 0, _message, _gasLimit);
emit DepositERC20(_token, l2USDC, _from, _to, _amount, _data);
}
}

View File

@@ -24,12 +24,12 @@ contract L1MessageQueue is OwnableUpgradeable, IL1MessageQueue {
/// @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);
event UpdateGasOracle(address _oldGasOracle, address _newGasOracle);
/// @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);
event UpdateEnforcedTxGateway(address _oldGateway, address _newGateway);
/// @notice Emitted when owner updates max gas limit.
/// @param _oldMaxGasLimit The old max gas limit.

View File

@@ -19,9 +19,8 @@ contract L2GasPriceOracle is OwnableUpgradeable, IL2GasPriceOracle {
event UpdateWhitelist(address _oldWhitelist, address _newWhitelist);
/// @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 L2BaseFeeUpdated(uint256 oldL2BaseFee, uint256 newL2BaseFee);
/// @param l2BaseFee The current l2 base fee updated.
event L2BaseFeeUpdated(uint256 l2BaseFee);
/// @notice Emitted when intrinsic params are updated.
/// @param txGas The intrinsic gas for transaction.
@@ -131,14 +130,13 @@ contract L2GasPriceOracle is OwnableUpgradeable, IL2GasPriceOracle {
}
/// @notice Allows the owner to modify the l2 base fee.
/// @param _newL2BaseFee The new l2 base fee.
function setL2BaseFee(uint256 _newL2BaseFee) external {
/// @param _l2BaseFee The new l2 base fee.
function setL2BaseFee(uint256 _l2BaseFee) external {
require(whitelist.isSenderAllowed(msg.sender), "Not whitelisted sender");
uint256 _oldL2BaseFee = l2BaseFee;
l2BaseFee = _newL2BaseFee;
l2BaseFee = _l2BaseFee;
emit L2BaseFeeUpdated(_oldL2BaseFee, _newL2BaseFee);
emit L2BaseFeeUpdated(_l2BaseFee);
}
/************************

View File

@@ -3,7 +3,6 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {IL1MessageQueue} from "./IL1MessageQueue.sol";
import {IScrollChain} from "./IScrollChain.sol";
@@ -16,7 +15,7 @@ import {IRollupVerifier} from "../../libraries/verifier/IRollupVerifier.sol";
/// @title ScrollChain
/// @notice This contract maintains data for the Scroll rollup.
contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
contract ScrollChain is OwnableUpgradeable, IScrollChain {
/**********
* Events *
**********/
@@ -34,7 +33,7 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
/// @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);
event UpdateVerifier(address oldVerifier, address newVerifier);
/// @notice Emitted when the value of `maxNumL2TxInChunk` is updated.
/// @param oldMaxNumL2TxInChunk The old value of `maxNumL2TxInChunk`.
@@ -166,7 +165,7 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
bytes calldata _parentBatchHeader,
bytes[] memory _chunks,
bytes calldata _skippedL1MessageBitmap
) external override OnlySequencer whenNotPaused {
) external override OnlySequencer {
require(_version == 0, "invalid version");
// check whether the batch is empty
@@ -292,7 +291,7 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
bytes32 _postStateRoot,
bytes32 _withdrawRoot,
bytes calldata _aggrProof
) external override OnlyProver whenNotPaused {
) external override OnlyProver {
require(_prevStateRoot != bytes32(0), "previous state root is zero");
require(_postStateRoot != bytes32(0), "new state root is zero");
@@ -356,36 +355,24 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
* Restricted Functions *
************************/
/// @notice Add an account to the sequencer list.
/// @param _account The address of account to add.
function addSequencer(address _account) external onlyOwner {
isSequencer[_account] = true;
/// @notice Update the status of sequencer.
/// @dev This function can only called by contract owner.
/// @param _account The address of account to update.
/// @param _status The status of the account to update.
function updateSequencer(address _account, bool _status) external onlyOwner {
isSequencer[_account] = _status;
emit UpdateSequencer(_account, true);
emit UpdateSequencer(_account, _status);
}
/// @notice Remove an account from the sequencer list.
/// @param _account The address of account to remove.
function removeSequencer(address _account) external onlyOwner {
isSequencer[_account] = false;
/// @notice Update the status of prover.
/// @dev This function can only called by contract owner.
/// @param _account The address of account to update.
/// @param _status The status of the account to update.
function updateProver(address _account, bool _status) external onlyOwner {
isProver[_account] = _status;
emit UpdateSequencer(_account, false);
}
/// @notice Add an account to the prover list.
/// @param _account The address of account to add.
function addProver(address _account) external onlyOwner {
isProver[_account] = true;
emit UpdateProver(_account, true);
}
/// @notice Add an account from the prover list.
/// @param _account The address of account to remove.
function removeProver(address _account) external onlyOwner {
isProver[_account] = false;
emit UpdateProver(_account, false);
emit UpdateProver(_account, _status);
}
/// @notice Update the address verifier contract.
@@ -406,16 +393,6 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
emit UpdateMaxNumL2TxInChunk(_oldMaxNumL2TxInChunk, _maxNumL2TxInChunk);
}
/// @notice Pause the contract
/// @param _status The pause status to update.
function setPause(bool _status) external onlyOwner {
if (_status) {
_pause();
} else {
_unpause();
}
}
/**********************
* Internal Functions *
**********************/
@@ -492,7 +469,6 @@ contract ScrollChain is OwnableUpgradeable, PausableUpgradeable, IScrollChain {
// concatenate l2 transaction hashes
uint256 _numTransactionsInBlock = ChunkCodec.numTransactions(blockPtr);
require(_numTransactionsInBlock >= _numL1MessagesInBlock, "num txs less than num L1 msgs");
for (uint256 j = _numL1MessagesInBlock; j < _numTransactionsInBlock; j++) {
bytes32 txHash;
(txHash, l2TxPtr) = ChunkCodec.loadL2TxHash(l2TxPtr);

View File

@@ -5,15 +5,6 @@ pragma solidity ^0.8.16;
import {IScrollMessenger} from "../libraries/IScrollMessenger.sol";
interface IL2ScrollMessenger is IScrollMessenger {
/**********
* Events *
**********/
/// @notice Emitted when the maximum number of times each message can fail in L2 is updated.
/// @param oldMaxFailedExecutionTimes The old maximum number of times each message can fail in L2.
/// @param newMaxFailedExecutionTimes The new maximum number of times each message can fail in L2.
event UpdateMaxFailedExecutionTimes(uint256 oldMaxFailedExecutionTimes, uint256 newMaxFailedExecutionTimes);
/*****************************
* Public Mutating Functions *
*****************************/

View File

@@ -2,8 +2,12 @@
pragma solidity =0.8.16;
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {IL2ScrollMessenger} from "./IL2ScrollMessenger.sol";
import {L2MessageQueue} from "./predeploys/L2MessageQueue.sol";
import {IL1BlockContainer} from "./predeploys/IL1BlockContainer.sol";
import {IL1GasPriceOracle} from "./predeploys/IL1GasPriceOracle.sol";
import {PatriciaMerkleTrieVerifier} from "../libraries/verifier/PatriciaMerkleTrieVerifier.sol";
import {ScrollConstants} from "../libraries/constants/ScrollConstants.sol";
@@ -22,7 +26,15 @@ import {ScrollMessengerBase} from "../libraries/ScrollMessengerBase.sol";
///
/// @dev It should be a predeployed contract on layer 2 and should hold infinite amount
/// of Ether (Specifically, `uint256(-1)`), which can be initialized in Genesis Block.
contract L2ScrollMessenger is ScrollMessengerBase, IL2ScrollMessenger {
contract L2ScrollMessenger is ScrollMessengerBase, PausableUpgradeable, IL2ScrollMessenger {
/**********
* Events *
**********/
/// @notice Emitted when the maximum number of times each message can fail in L2 is updated.
/// @param maxFailedExecutionTimes The new maximum number of times each message can fail in L2.
event UpdateMaxFailedExecutionTimes(uint256 maxFailedExecutionTimes);
/*************
* Constants *
*************/
@@ -56,8 +68,9 @@ contract L2ScrollMessenger is ScrollMessengerBase, IL2ScrollMessenger {
messageQueue = _messageQueue;
}
function initialize(address _counterpart) external initializer {
ScrollMessengerBase.__ScrollMessengerBase_init(_counterpart, address(0));
function initialize(address _counterpart, address _feeVault) external initializer {
PausableUpgradeable.__Pausable_init();
ScrollMessengerBase._initialize(_counterpart, _feeVault);
maxFailedExecutionTimes = 3;
}
@@ -109,16 +122,26 @@ contract L2ScrollMessenger is ScrollMessengerBase, IL2ScrollMessenger {
* Restricted Functions *
************************/
/// @notice Pause the contract
/// @dev This function can only called by contract owner.
/// @param _status The pause status to update.
function setPause(bool _status) external onlyOwner {
if (_status) {
_pause();
} else {
_unpause();
}
}
/// @notice Update max failed execution times.
/// @dev This function can only called by contract owner.
/// @param _newMaxFailedExecutionTimes The new max failed execution times.
function updateMaxFailedExecutionTimes(uint256 _newMaxFailedExecutionTimes) external onlyOwner {
require(_newMaxFailedExecutionTimes > 0, "maxFailedExecutionTimes cannot be zero");
/// @param _maxFailedExecutionTimes The new max failed execution times.
function updateMaxFailedExecutionTimes(uint256 _maxFailedExecutionTimes) external onlyOwner {
require(_maxFailedExecutionTimes > 0, "maxFailedExecutionTimes cannot be zero");
uint256 _oldMaxFailedExecutionTimes = maxFailedExecutionTimes;
maxFailedExecutionTimes = _newMaxFailedExecutionTimes;
maxFailedExecutionTimes = _maxFailedExecutionTimes;
emit UpdateMaxFailedExecutionTimes(_oldMaxFailedExecutionTimes, _newMaxFailedExecutionTimes);
emit UpdateMaxFailedExecutionTimes(_maxFailedExecutionTimes);
}
/**********************

View File

@@ -11,18 +11,15 @@ interface IL2GatewayRouter is IL2ETHGateway, IL2ERC20Gateway {
**********/
/// @notice Emitted when the address of ETH Gateway is updated.
/// @param oldETHGateway The address of the old ETH Gateway.
/// @param newEthGateway The address of the new ETH Gateway.
event SetETHGateway(address indexed oldETHGateway, address indexed newEthGateway);
/// @param ethGateway The address of new ETH Gateway.
event SetETHGateway(address indexed ethGateway);
/// @notice Emitted when the address of default ERC20 Gateway is updated.
/// @param oldDefaultERC20Gateway The address of the old default ERC20 Gateway.
/// @param newDefaultERC20Gateway The address of the new default ERC20 Gateway.
event SetDefaultERC20Gateway(address indexed oldDefaultERC20Gateway, address indexed newDefaultERC20Gateway);
/// @param defaultERC20Gateway The address of new default ERC20 Gateway.
event SetDefaultERC20Gateway(address indexed defaultERC20Gateway);
/// @notice Emitted when the `gateway` for `token` is updated.
/// @param token The address of token updated.
/// @param oldGateway The corresponding address of the old gateway.
/// @param newGateway The corresponding address of the new gateway.
event SetERC20Gateway(address indexed token, address indexed oldGateway, address indexed newGateway);
/// @param gateway The corresponding address of gateway updated.
event SetERC20Gateway(address indexed token, address indexed gateway);
}

View File

@@ -2,27 +2,29 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {IL2ERC20Gateway, L2ERC20Gateway} from "./L2ERC20Gateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IL1ERC20Gateway} from "../../L1/gateways/IL1ERC20Gateway.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {IScrollERC20Upgradeable} from "../../libraries/token/IScrollERC20Upgradeable.sol";
import {ScrollGatewayBase, IScrollGateway} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {IScrollERC20} from "../../libraries/token/IScrollERC20.sol";
/// @title L2ERC20Gateway
/// @notice The `L2ERC20Gateway` is used to withdraw custom ERC20 compatible tokens on layer 2 and
/// finalize deposit the tokens from layer 1.
/// @dev The withdrawn tokens tokens will be burned directly. On finalizing deposit, the corresponding
/// tokens will be minted and transfered to the recipient.
contract L2CustomERC20Gateway is L2ERC20Gateway {
contract L2CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L2ERC20Gateway {
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC20 token is updated.
/// @param l2Token The address of corresponding ERC20 token in layer 2.
/// @param oldL1Token The address of the old corresponding ERC20 token in layer 1.
/// @param newL1Token The address of the new corresponding ERC20 token in layer 1.
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token);
/// @param _l2Token The address of corresponding ERC20 token on layer 2.
/// @param _l1Token The address of ERC20 token on layer 1.
event UpdateTokenMapping(address _l2Token, address _l1Token);
/*************
* Variables *
@@ -45,6 +47,7 @@ contract L2CustomERC20Gateway is L2ERC20Gateway {
address _messenger
) external initializer {
require(_router != address(0), "zero router address");
OwnableUpgradeable.__Ownable_init();
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
}
@@ -80,7 +83,7 @@ contract L2CustomERC20Gateway is L2ERC20Gateway {
require(_l1Token != address(0), "token address cannot be 0");
require(_l1Token == tokenMapping[_l2Token], "l1 token mismatch");
IScrollERC20Upgradeable(_l2Token).mint(_to, _amount);
IScrollERC20(_l2Token).mint(_to, _amount);
_doCallback(_to, _data);
@@ -97,10 +100,9 @@ contract L2CustomERC20Gateway is L2ERC20Gateway {
function updateTokenMapping(address _l2Token, address _l1Token) external onlyOwner {
require(_l1Token != address(0), "token address cannot be 0");
address _oldL1Token = tokenMapping[_l2Token];
tokenMapping[_l2Token] = _l1Token;
emit UpdateTokenMapping(_l2Token, _oldL1Token, _l1Token);
emit UpdateTokenMapping(_l2Token, _l1Token);
}
/**********************
@@ -127,7 +129,7 @@ contract L2CustomERC20Gateway is L2ERC20Gateway {
}
// 2. Burn token.
IScrollERC20Upgradeable(_token).burn(_from, _amount);
IScrollERC20(_token).burn(_from, _amount);
// 3. Generate message passed to L1StandardERC20Gateway.
bytes memory _message = abi.encodeCall(

View File

@@ -2,12 +2,14 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
import {ERC1155HolderUpgradeable, ERC1155ReceiverUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155HolderUpgradeable.sol";
import {IL2ERC1155Gateway} from "./IL2ERC1155Gateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IL1ERC1155Gateway} from "../../L1/gateways/IL1ERC1155Gateway.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {ScrollGatewayBase, IScrollGateway} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {IScrollERC1155} from "../../libraries/token/IScrollERC1155.sol";
/// @title L2ERC1155Gateway
@@ -17,16 +19,15 @@ import {IScrollERC1155} from "../../libraries/token/IScrollERC1155.sol";
/// NFT will be minted and transfered to the recipient.
///
/// This will be changed if we have more specific scenarios.
contract L2ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL2ERC1155Gateway {
contract L2ERC1155Gateway is OwnableUpgradeable, ERC1155HolderUpgradeable, ScrollGatewayBase, IL2ERC1155Gateway {
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC1155 token is updated.
/// @param l2Token The address of corresponding ERC1155 token in layer 2.
/// @param oldL1Token The address of the old corresponding ERC1155 token in layer 1.
/// @param newL1Token The address of the new corresponding ERC1155 token in layer 1.
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token);
/// @param _l2Token The address of corresponding ERC1155 token on layer 2.
/// @param _l1Token The address of ERC1155 token on layer 1.
event UpdateTokenMapping(address _l2Token, address _l1Token);
/*************
* Variables *
@@ -44,6 +45,7 @@ contract L2ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL2ERC
}
function initialize(address _counterpart, address _messenger) external initializer {
OwnableUpgradeable.__Ownable_init();
ERC1155HolderUpgradeable.__ERC1155Holder_init();
ERC1155ReceiverUpgradeable.__ERC1155Receiver_init();
@@ -140,10 +142,9 @@ contract L2ERC1155Gateway is ERC1155HolderUpgradeable, ScrollGatewayBase, IL2ERC
function updateTokenMapping(address _l2Token, address _l1Token) external onlyOwner {
require(_l1Token != address(0), "token address cannot be 0");
address _oldL1Token = tokenMapping[_l2Token];
tokenMapping[_l2Token] = _l1Token;
emit UpdateTokenMapping(_l2Token, _oldL1Token, _l1Token);
emit UpdateTokenMapping(_l2Token, _l1Token);
}
/**********************

View File

@@ -4,11 +4,9 @@ pragma solidity ^0.8.16;
import {IL2ERC20Gateway} from "./IL2ERC20Gateway.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
// solhint-disable no-empty-blocks
abstract contract L2ERC20Gateway is ScrollGatewayBase, IL2ERC20Gateway {
abstract contract L2ERC20Gateway is IL2ERC20Gateway {
/*************
* Variables *
*************/

View File

@@ -2,12 +2,14 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import {ERC721HolderUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol";
import {IL2ERC721Gateway} from "./IL2ERC721Gateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IL1ERC721Gateway} from "../../L1/gateways/IL1ERC721Gateway.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {ScrollGatewayBase, IScrollGateway} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {IScrollERC721} from "../../libraries/token/IScrollERC721.sol";
/// @title L2ERC721Gateway
@@ -17,16 +19,15 @@ import {IScrollERC721} from "../../libraries/token/IScrollERC721.sol";
/// NFT will be minted and transfered to the recipient.
///
/// This will be changed if we have more specific scenarios.
contract L2ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL2ERC721Gateway {
contract L2ERC721Gateway is OwnableUpgradeable, ERC721HolderUpgradeable, ScrollGatewayBase, IL2ERC721Gateway {
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC721 token is updated.
/// @param l2Token The address of corresponding ERC721 token in layer 2.
/// @param oldL1Token The address of the old corresponding ERC721 token in layer 1.
/// @param newL1Token The address of the new corresponding ERC721 token in layer 1.
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token);
/// @param _l2Token The address of corresponding ERC721 token on layer 2.
/// @param _l1Token The address of ERC721 token on layer 1.
event UpdateTokenMapping(address _l2Token, address _l1Token);
/*************
* Variables *
@@ -44,6 +45,7 @@ contract L2ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL2ERC72
}
function initialize(address _counterpart, address _messenger) external initializer {
OwnableUpgradeable.__Ownable_init();
ERC721HolderUpgradeable.__ERC721Holder_init();
ScrollGatewayBase._initialize(_counterpart, address(0), _messenger);
@@ -135,10 +137,9 @@ contract L2ERC721Gateway is ERC721HolderUpgradeable, ScrollGatewayBase, IL2ERC72
function updateTokenMapping(address _l2Token, address _l1Token) external onlyOwner {
require(_l1Token != address(0), "token address cannot be 0");
address _oldL1Token = tokenMapping[_l2Token];
tokenMapping[_l2Token] = _l1Token;
emit UpdateTokenMapping(_l2Token, _oldL1Token, _l1Token);
emit UpdateTokenMapping(_l2Token, _l1Token);
}
/**********************

View File

@@ -2,6 +2,8 @@
pragma solidity =0.8.16;
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IL1ETHGateway} from "../../L1/gateways/IL1ETHGateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IL2ETHGateway} from "./IL2ETHGateway.sol";
@@ -13,7 +15,7 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// finalize deposit ETH from layer 1.
/// @dev The ETH are not held in the gateway. The ETH will be sent to the `L2ScrollMessenger` contract.
/// On finalizing deposit, the Ether will be transfered from `L2ScrollMessenger`, then transfer to recipient.
contract L2ETHGateway is ScrollGatewayBase, IL2ETHGateway {
contract L2ETHGateway is Initializable, ScrollGatewayBase, IL2ETHGateway {
/***************
* Constructor *
***************/

View File

@@ -7,6 +7,9 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own
import {IL2GatewayRouter} from "./IL2GatewayRouter.sol";
import {IL2ETHGateway} from "./IL2ETHGateway.sol";
import {IL2ERC20Gateway} from "./IL2ERC20Gateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IL1ETHGateway} from "../../L1/gateways/IL1ETHGateway.sol";
import {IScrollGateway} from "../../libraries/gateway/IScrollGateway.sol";
/// @title L2GatewayRouter
/// @notice The `L2GatewayRouter` is the main entry for withdrawing Ether and ERC20 tokens.
@@ -42,13 +45,13 @@ contract L2GatewayRouter is OwnableUpgradeable, IL2GatewayRouter {
// it can be zero during initialization
if (_defaultERC20Gateway != address(0)) {
defaultERC20Gateway = _defaultERC20Gateway;
emit SetDefaultERC20Gateway(address(0), _defaultERC20Gateway);
emit SetDefaultERC20Gateway(_defaultERC20Gateway);
}
// it can be zero during initialization
if (_ethGateway != address(0)) {
ethGateway = _ethGateway;
emit SetETHGateway(address(0), _ethGateway);
emit SetETHGateway(_ethGateway);
}
}
@@ -179,22 +182,20 @@ contract L2GatewayRouter is OwnableUpgradeable, IL2GatewayRouter {
/// @notice Update the address of ETH gateway contract.
/// @dev This function should only be called by contract owner.
/// @param _newEthGateway The address to update.
function setETHGateway(address _newEthGateway) external onlyOwner {
address _oldEthGateway = ethGateway;
ethGateway = _newEthGateway;
/// @param _ethGateway The address to update.
function setETHGateway(address _ethGateway) external onlyOwner {
ethGateway = _ethGateway;
emit SetETHGateway(_oldEthGateway, _newEthGateway);
emit SetETHGateway(_ethGateway);
}
/// @notice Update the address of default ERC20 gateway contract.
/// @dev This function should only be called by contract owner.
/// @param _newDefaultERC20Gateway The address to update.
function setDefaultERC20Gateway(address _newDefaultERC20Gateway) external onlyOwner {
address _oldDefaultERC20Gateway = defaultERC20Gateway;
defaultERC20Gateway = _newDefaultERC20Gateway;
/// @param _defaultERC20Gateway The address to update.
function setDefaultERC20Gateway(address _defaultERC20Gateway) external onlyOwner {
defaultERC20Gateway = _defaultERC20Gateway;
emit SetDefaultERC20Gateway(_oldDefaultERC20Gateway, _newDefaultERC20Gateway);
emit SetDefaultERC20Gateway(_defaultERC20Gateway);
}
/// @notice Update the mapping from token address to gateway address.
@@ -205,10 +206,9 @@ contract L2GatewayRouter is OwnableUpgradeable, IL2GatewayRouter {
require(_tokens.length == _gateways.length, "length mismatch");
for (uint256 i = 0; i < _tokens.length; i++) {
address _oldGateway = ERC20Gateway[_tokens[i]];
ERC20Gateway[_tokens[i]] = _gateways[i];
emit SetERC20Gateway(_tokens[i], _oldGateway, _gateways[i]);
emit SetERC20Gateway(_tokens[i], _gateways[i]);
}
}
}

View File

@@ -2,15 +2,18 @@
pragma solidity =0.8.16;
import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {IL2ERC20Gateway, L2ERC20Gateway} from "./L2ERC20Gateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IL1ERC20Gateway} from "../../L1/gateways/IL1ERC20Gateway.sol";
import {IScrollERC20Upgradeable} from "../../libraries/token/IScrollERC20Upgradeable.sol";
import {IScrollERC20} from "../../libraries/token/IScrollERC20.sol";
import {ScrollStandardERC20} from "../../libraries/token/ScrollStandardERC20.sol";
import {IScrollStandardERC20Factory} from "../../libraries/token/IScrollStandardERC20Factory.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {ScrollGatewayBase, IScrollGateway} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// @title L2StandardERC20Gateway
/// @notice The `L2StandardERC20Gateway` is used to withdraw standard ERC20 tokens on layer 2 and
@@ -18,8 +21,9 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// @dev The withdrawn ERC20 tokens will be burned directly. On finalizing deposit, the corresponding
/// token will be minted and transfered to the recipient. Any ERC20 that requires non-standard functionality
/// should use a separate gateway.
contract L2StandardERC20Gateway is L2ERC20Gateway {
using AddressUpgradeable for address;
contract L2StandardERC20Gateway is Initializable, ScrollGatewayBase, L2ERC20Gateway {
using SafeERC20 for IERC20;
using Address for address;
/*************
* Variables *
@@ -110,7 +114,7 @@ contract L2StandardERC20Gateway is L2ERC20Gateway {
_deployL2Token(_deployData, _l1Token);
}
IScrollERC20Upgradeable(_l2Token).mint(_to, _amount);
IScrollERC20(_l2Token).mint(_to, _amount);
_doCallback(_to, _callData);
@@ -141,7 +145,7 @@ contract L2StandardERC20Gateway is L2ERC20Gateway {
require(_l1Token != address(0), "no corresponding l1 token");
// 2. Burn token.
IScrollERC20Upgradeable(_token).burn(_from, _amount);
IScrollERC20(_token).burn(_from, _amount);
// 3. Generate message passed to L1StandardERC20Gateway.
bytes memory _message = abi.encodeCall(

View File

@@ -2,14 +2,15 @@
pragma solidity =0.8.16;
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IL2ERC20Gateway, L2ERC20Gateway} from "./L2ERC20Gateway.sol";
import {IL2ScrollMessenger} from "../IL2ScrollMessenger.sol";
import {IWETH} from "../../interfaces/IWETH.sol";
import {IL1ERC20Gateway} from "../../L1/gateways/IL1ERC20Gateway.sol";
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {ScrollGatewayBase, IScrollGateway} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// @title L2WETHGateway
/// @notice The `L2WETHGateway` contract is used to withdraw `WETH` token on layer 2 and
@@ -18,8 +19,8 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// then the Ether will be sent to the `L2ScrollMessenger` contract.
/// On finalizing deposit, the Ether will be transfered from `L2ScrollMessenger`, then
/// wrapped as WETH and finally transfer to recipient.
contract L2WETHGateway is L2ERC20Gateway {
using SafeERC20Upgradeable for IERC20Upgradeable;
contract L2WETHGateway is Initializable, ScrollGatewayBase, L2ERC20Gateway {
using SafeERC20 for IERC20;
/*************
* Constants *
@@ -88,7 +89,7 @@ contract L2WETHGateway is L2ERC20Gateway {
require(_amount == msg.value, "msg.value mismatch");
IWETH(_l2Token).deposit{value: _amount}();
IERC20Upgradeable(_l2Token).safeTransfer(_to, _amount);
IERC20(_l2Token).safeTransfer(_to, _amount);
_doCallback(_to, _data);
@@ -117,7 +118,7 @@ contract L2WETHGateway is L2ERC20Gateway {
}
// 2. Transfer token into this contract.
IERC20Upgradeable(_token).safeTransferFrom(_from, address(this), _amount);
IERC20(_token).safeTransferFrom(_from, address(this), _amount);
IWETH(_token).withdraw(_amount);
// 3. Generate message passed to L2StandardERC20Gateway.

View File

@@ -2,11 +2,11 @@
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {IFiatToken} from "../../../interfaces/IFiatToken.sol";
import {IUSDCDestinationBridge} from "../../../interfaces/IUSDCDestinationBridge.sol";
import {IL1ERC20Gateway} from "../../../L1/gateways/IL1ERC20Gateway.sol";
import {IL2ScrollMessenger} from "../../IL2ScrollMessenger.sol";
import {IL2ERC20Gateway} from "../IL2ERC20Gateway.sol";
@@ -17,7 +17,7 @@ import {L2ERC20Gateway} from "../L2ERC20Gateway.sol";
/// @title L2USDCGateway
/// @notice The `L2USDCGateway` contract is used to withdraw `USDC` token on layer 2 and
/// finalize deposit `USDC` from layer 1.
contract L2USDCGateway is L2ERC20Gateway, IUSDCDestinationBridge {
contract L2USDCGateway is OwnableUpgradeable, ScrollGatewayBase, L2ERC20Gateway {
using SafeERC20Upgradeable for IERC20Upgradeable;
/*************
@@ -34,8 +34,6 @@ contract L2USDCGateway is L2ERC20Gateway, IUSDCDestinationBridge {
* Variables *
*************/
address public circleCaller;
bool public depositPaused;
bool public withdrawPaused;
@@ -58,6 +56,8 @@ contract L2USDCGateway is L2ERC20Gateway, IUSDCDestinationBridge {
) external initializer {
require(_router != address(0), "zero router address");
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
OwnableUpgradeable.__Ownable_init();
}
/*************************
@@ -94,8 +94,7 @@ contract L2USDCGateway is L2ERC20Gateway, IUSDCDestinationBridge {
require(IFiatToken(_l2Token).mint(_to, _amount), "mint USDC failed");
// disable call for USDC
// _doCallback(_to, _data);
_doCallback(_to, _data);
emit FinalizeDepositERC20(_l1Token, _l2Token, _from, _to, _amount, _data);
}
@@ -104,19 +103,6 @@ contract L2USDCGateway is L2ERC20Gateway, IUSDCDestinationBridge {
* Public Restricted Functions *
*******************************/
/// @inheritdoc IUSDCDestinationBridge
function transferUSDCRoles(address _owner) external {
require(msg.sender == circleCaller, "only circle caller");
_transferOwnership(_owner);
}
/// @notice Update the Circle EOA address.
/// @param _caller The address to update.
function updateCircleCaller(address _caller) external onlyOwner {
circleCaller = _caller;
}
/// @notice Change the deposit pause status of this contract.
/// @param _paused The new status, `true` means paused and `false` means not paused.
function pauseDeposit(bool _paused) external onlyOwner {
@@ -150,7 +136,6 @@ contract L2USDCGateway is L2ERC20Gateway, IUSDCDestinationBridge {
if (router == msg.sender) {
(_from, _data) = abi.decode(_data, (address, bytes));
}
require(_data.length == 0, "call is not allowed");
// 2. Transfer token into this contract.
IERC20Upgradeable(_token).safeTransferFrom(_from, address(this), _amount);

View File

@@ -1,156 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {ITokenMessenger} from "../../../interfaces/ITokenMessenger.sol";
import {IL1ERC20Gateway} from "../../../L1/gateways/IL1ERC20Gateway.sol";
import {IL2ScrollMessenger} from "../../IL2ScrollMessenger.sol";
import {IL2ERC20Gateway} from "../IL2ERC20Gateway.sol";
import {CCTPGatewayBase} from "../../../libraries/gateway/CCTPGatewayBase.sol";
import {ScrollGatewayBase} from "../../../libraries/gateway/ScrollGatewayBase.sol";
import {L2ERC20Gateway} from "../L2ERC20Gateway.sol";
/// @title L2USDCGatewayCCTP
/// @notice The `L2USDCGatewayCCTP` contract is used to withdraw `USDC` token in layer 2 and
/// finalize deposit `USDC` from layer 1.
contract L2USDCGatewayCCTP is CCTPGatewayBase, L2ERC20Gateway {
using SafeERC20Upgradeable for IERC20Upgradeable;
/***************
* Constructor *
***************/
constructor(
address _l1USDC,
address _l2USDC,
uint32 _destinationDomain
) CCTPGatewayBase(_l1USDC, _l2USDC, _destinationDomain) {}
/// @notice Initialize the storage of L2USDCGatewayCCTP.
/// @param _counterpart The address of L1USDCGatewayCCTP in L1.
/// @param _router The address of L2GatewayRouter.
/// @param _messenger The address of L2ScrollMessenger.
/// @param _cctpMessenger The address of TokenMessenger in local domain.
/// @param _cctpTransmitter The address of MessageTransmitter in local domain.
function initialize(
address _counterpart,
address _router,
address _messenger,
address _cctpMessenger,
address _cctpTransmitter
) external initializer {
require(_router != address(0), "zero router address");
ScrollGatewayBase._initialize(_counterpart, _router, _messenger);
CCTPGatewayBase._initialize(_cctpMessenger, _cctpTransmitter);
OwnableUpgradeable.__Ownable_init();
}
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IL2ERC20Gateway
function getL1ERC20Address(address) external view override returns (address) {
return l1USDC;
}
/// @inheritdoc IL2ERC20Gateway
function getL2ERC20Address(address) public view override returns (address) {
return l2USDC;
}
/*****************************
* Public Mutating Functions *
*****************************/
/// @inheritdoc IL2ERC20Gateway
/// @dev The function will not mint the USDC, users need to call `claimUSDC` after this function is done.
function finalizeDepositERC20(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes memory _data
) external payable override onlyCallByCounterpart {
require(msg.value == 0, "nonzero msg.value");
require(_l1Token == l1USDC, "l1 token not USDC");
require(_l2Token == l2USDC, "l2 token not USDC");
uint256 _nonce;
(_nonce, _data) = abi.decode(_data, (uint256, bytes));
require(status[_nonce] == CCTPMessageStatus.None, "message relayed");
status[_nonce] = CCTPMessageStatus.Pending;
emit FinalizeDepositERC20(_l1Token, _l2Token, _from, _to, _amount, _data);
}
/*******************************
* Public Restricted Functions *
*******************************/
/// @notice Update the CCTP contract addresses.
/// @param _messenger The address of TokenMessenger in local domain.
/// @param _transmitter The address of MessageTransmitter in local domain.
function updateCCTPContracts(address _messenger, address _transmitter) external onlyOwner {
cctpMessenger = _messenger;
cctpTransmitter = _transmitter;
}
/**********************
* Internal Functions *
**********************/
/// @inheritdoc L2ERC20Gateway
function _withdraw(
address _token,
address _to,
uint256 _amount,
bytes memory _data,
uint256 _gasLimit
) internal virtual override {
require(_amount > 0, "withdraw zero amount");
require(_token == l2USDC, "only USDC is allowed");
// 1. Extract real sender if this call is from L1GatewayRouter.
address _from = msg.sender;
if (router == msg.sender) {
(_from, _data) = abi.decode(_data, (address, bytes));
}
// 2. Transfer token into this contract.
IERC20Upgradeable(_token).safeTransferFrom(_from, address(this), _amount);
// 3. Burn token through CCTP TokenMessenger
uint256 _nonce = ITokenMessenger(cctpMessenger).depositForBurnWithCaller(
_amount,
destinationDomain,
bytes32(uint256(uint160(_to))),
address(this),
bytes32(uint256(uint160(counterpart)))
);
// 4. Generate message passed to L1USDCGateway.
address _l1USDC = l1USDC;
bytes memory _message = abi.encodeWithSelector(
IL1ERC20Gateway.finalizeWithdrawERC20.selector,
_l1USDC,
_token,
_from,
_to,
_amount,
abi.encode(_nonce, _data)
);
// 4. Send message to L1ScrollMessenger.
IL2ScrollMessenger(messenger).sendMessage{value: msg.value}(counterpart, 0, _message, _gasLimit);
emit WithdrawERC20(_l1USDC, _token, _from, _to, _amount, _data);
}
}

View File

@@ -5,6 +5,7 @@ pragma solidity =0.8.16;
import {OwnableBase} from "../../libraries/common/OwnableBase.sol";
import {IWhitelist} from "../../libraries/common/IWhitelist.sol";
import {IL1BlockContainer} from "./IL1BlockContainer.sol";
import {IL1GasPriceOracle} from "./IL1GasPriceOracle.sol";
contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {

View File

@@ -1,6 +1,6 @@
A library for interacting with Scroll contracts.
This library includes contracts and interfaces needed to interact with the Scroll Smart Contracts deployed on both Layer 1 and Layer 2. This includes deposting and withdrawing ETH, ERC20 tokens and NFTs or sending arbitrary messages.
This library includes contracts and interfaces needed to interact with the Scroll Smart Contracts deployed on both Layer 1 and Layer 2. This includes deposting and withdrawing ETH, ERC20 tokens and NFTs or sending arbitrary messages.
# Overview
@@ -21,11 +21,10 @@ pragma solidity 0.8.20;
import "@scroll-tech/contracts/L1/gateways/IL1ETHGateway.sol";
contract MyContract {
function bridgeETH(address scrollBridge, uint256 gasLimit) public payable {
IL1ETHGateway(scrollBridge).depositETH(msg.sender, msg.value, gasLimit);
}
function bridgeETH(address scrollBridge, uint gasLimit) public payable {
IL1ETHGateway(scrollBridge).depositETH(msg.sender, msg.value, gasLimit);
}
}
```
Visit the Bridge Documentation for API reference, architecture overview and guides with code examples.

View File

@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IERC20Metadata {
function symbol() external view returns (string memory);
function name() external view returns (string memory);
function decimals() external view returns (uint8);
}

View File

@@ -1,16 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IMessageTransmitter {
function usedNonces(bytes32 _sourceAndNonce) external view returns (uint256);
/**
* @notice Receives an incoming message, validating the header and passing
* the body to application-specific handler.
* @param message The message raw bytes
* @param signature The message signature
* @return success bool, true if successful
*/
function receiveMessage(bytes calldata message, bytes calldata signature) external returns (bool success);
}

View File

@@ -1,63 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface ITokenMessenger {
/**
* @notice Deposits and burns tokens from sender to be minted on destination domain. The mint
* on the destination domain must be called by `destinationCaller`.
* WARNING: if the `destinationCaller` does not represent a valid address as bytes32, then it will not be possible
* to broadcast the message on the destination domain. This is an advanced feature, and the standard
* depositForBurn() should be preferred for use cases where a specific destination caller is not required.
* Emits a `DepositForBurn` event.
* @dev reverts if:
* - given destinationCaller is zero address
* - given burnToken is not supported
* - given destinationDomain has no TokenMessenger registered
* - transferFrom() reverts. For example, if sender's burnToken balance or approved allowance
* to this contract is less than `amount`.
* - burn() reverts. For example, if `amount` is 0.
* - MessageTransmitter returns false or reverts.
* @param amount amount of tokens to burn
* @param destinationDomain destination domain
* @param mintRecipient address of mint recipient on destination domain
* @param burnToken address of contract to burn deposited tokens, on local domain
* @param destinationCaller caller on the destination domain, as bytes32
* @return nonce unique nonce reserved by message
*/
function depositForBurnWithCaller(
uint256 amount,
uint32 destinationDomain,
bytes32 mintRecipient,
address burnToken,
bytes32 destinationCaller
) external returns (uint64 nonce);
/**
* @notice Replace a BurnMessage to change the mint recipient and/or
* destination caller. Allows the sender of a previous BurnMessage
* (created by depositForBurn or depositForBurnWithCaller)
* to send a new BurnMessage to replace the original.
* The new BurnMessage will reuse the amount and burn token of the original,
* without requiring a new deposit.
* @dev The new message will reuse the original message's nonce. For a
* given nonce, all replacement message(s) and the original message are
* valid to broadcast on the destination domain, until the first message
* at the nonce confirms, at which point all others are invalidated.
* Note: The msg.sender of the replaced message must be the same as the
* msg.sender of the original message.
* @param originalMessage original message bytes (to replace)
* @param originalAttestation original attestation bytes
* @param newDestinationCaller the new destination caller, which may be the
* same as the original destination caller, a new destination caller, or an empty
* destination caller (bytes32(0), indicating that any destination caller is valid.)
* @param newMintRecipient the new mint recipient, which may be the same as the
* original mint recipient, or different.
*/
function replaceDepositForBurn(
bytes calldata originalMessage,
bytes calldata originalAttestation,
bytes32 newDestinationCaller,
bytes32 newMintRecipient
) external;
}

View File

@@ -1,12 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
// Implement this on the source chain (Ethereum).
interface IUSDCBurnableSourceBridge {
/**
* @notice Called by Circle, this executes a burn on the source
* chain.
*/
function burnAllLockedUSDC() external;
}

View File

@@ -1,11 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
// Implement this on the destination chain (Scroll).
interface IUSDCDestinationBridge {
/**
* @notice Called by Circle, this transfers FiatToken roles to the designated owner.
*/
function transferUSDCRoles(address owner) external;
}

View File

@@ -3,20 +3,13 @@
pragma solidity ^0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {ScrollConstants} from "./constants/ScrollConstants.sol";
import {IScrollMessenger} from "./IScrollMessenger.sol";
// solhint-disable var-name-mixedcase
abstract contract ScrollMessengerBase is
OwnableUpgradeable,
PausableUpgradeable,
ReentrancyGuardUpgradeable,
IScrollMessenger
{
abstract contract ScrollMessengerBase is OwnableUpgradeable, IScrollMessenger {
/**********
* Events *
**********/
@@ -26,6 +19,14 @@ abstract contract ScrollMessengerBase is
/// @param _newFeeVault The address of new fee vault contract.
event UpdateFeeVault(address _oldFeeVault, address _newFeeVault);
/*************
* Constants *
*************/
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.5.0/contracts/security/ReentrancyGuard.sol
uint256 internal constant _NOT_ENTERED = 1;
uint256 internal constant _ENTERED = 2;
/*************
* Variables *
*************/
@@ -39,13 +40,31 @@ abstract contract ScrollMessengerBase is
/// @notice The address of fee vault, collecting cross domain messaging fee.
address public feeVault;
// @note move to ScrollMessengerBase in next big refactor
/// @dev The status of for non-reentrant check.
uint256 private _lock_status;
/// @dev The storage slots for future usage.
uint256[47] private __gap;
uint256[46] private __gap;
/**********************
* Function Modifiers *
**********************/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_lock_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_lock_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_lock_status = _NOT_ENTERED;
}
modifier notInExecution() {
require(
xDomainMessageSender == ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER,
@@ -58,18 +77,14 @@ abstract contract ScrollMessengerBase is
* Constructor *
***************/
function __ScrollMessengerBase_init(address _counterpart, address _feeVault) internal onlyInitializing {
function _initialize(address _counterpart, address _feeVault) internal {
OwnableUpgradeable.__Ownable_init();
PausableUpgradeable.__Pausable_init();
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();
// initialize to a nonzero value
xDomainMessageSender = ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER;
counterpart = _counterpart;
if (_feeVault != address(0)) {
feeVault = _feeVault;
}
feeVault = _feeVault;
}
// make sure only owner can send ether to messenger to avoid possible user fund loss.
@@ -89,17 +104,6 @@ abstract contract ScrollMessengerBase is
emit UpdateFeeVault(_oldFeeVault, _newFeeVault);
}
/// @notice Pause the contract
/// @dev This function can only called by contract owner.
/// @param _status The pause status to update.
function setPause(bool _status) external onlyOwner {
if (_status) {
_pause();
} else {
_unpause();
}
}
/**********************
* Internal Functions *
**********************/

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