Compare commits

..

34 Commits

Author SHA1 Message Date
ChuhanJin
e780994146 fix(bridge-history-api): fix error not return 0 (#685) 2023-07-28 22:18:44 +08:00
ChuhanJin
f9a0de0f16 feat(bridge-history-api): switch to v2 decoding (#683)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-28 13:55:55 +02:00
colin
3eb62880fe feat(orm): add more info for agg proving (#678) 2023-07-28 19:27:15 +08:00
Haichen Shen
e2612a3d88 fix(contracts): Fix typos in the contract function name and docs (#679) 2023-07-27 09:58:07 -07:00
Péter Garamvölgyi
530db9e2e1 fix(build): update verifier lib path (#682) 2023-07-27 13:48:14 +02:00
Péter Garamvölgyi
c12b1fd8f2 fix(contracts): adjust deployment scripts (#680) 2023-07-27 12:40:12 +02:00
Péter Garamvölgyi
bab1982c30 fix(build): include prover-stats-api in dockerfiles (#681) 2023-07-27 12:34:10 +02:00
Xi Lin
b0ee9fa519 refactor(contracts): OZ-L1-N01 Constant Not Using UPPER_CASE Format (#674) 2023-07-26 23:05:56 -07:00
Péter Garamvölgyi
d8cc69501e fix(contracts): initialize L2GasOracle with correct intrinsic gas params. (#677) 2023-07-26 10:00:39 +02:00
Haichen Shen
2eb458cf42 fix(contracts): OZ-L1-N10 SimpleGasOracle Is Not Used (#671) 2023-07-25 10:25:27 -07:00
Xi Lin
3832422bc9 fix(contracts): OZ-L2-L06 Initialization Performed Outside of Initialization Function (#652)
Co-authored-by: Haichen Shen <shenhaichen@gmail.com>
2023-07-25 10:24:53 -07:00
Xi Lin
4d96c12e7b fix(contracts): OZ-L1-N02 Error-Prone Call Encoding and OZ-L2-L03 Unsafe ABI Encoding (#668)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-24 23:05:54 +08:00
Xi Lin
f56997bf15 fix(contracts): OZ-L2-L07 Block Container Does Not Enforce Whitelist (#651)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-24 22:57:52 +08:00
Xi Lin
2bd9694348 fix(contracts): OZ-L2-L05 Lack of Event Emissions (#650)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-24 22:43:43 +08:00
Xi Lin
8b6c237d74 fix(contracts): OZ-L2-L01 Lack of Validation When Updating Maximum Failed Execution Tries (#649)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-24 22:29:05 +08:00
Xi Lin
0fc6d2a5e5 fix(contracts): OZ-L2-M02 WETH9 Approval Can Be Front-Run (#632)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-24 22:16:12 +08:00
Xi Lin
0ce3b182a8 fix(contracts): OZ-L2-M01 L2MessageQueue Stores Incorrect Value if not Initialized Before Appending (#630)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-24 22:04:55 +08:00
ChuhanJin
5c4f7c33fd refactor(bridge-history-api): use Gorm (#656)
Co-authored-by: vincent <419436363@qq.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
Co-authored-by: georgehao <haohongfan@gmail.com>
2023-07-24 17:35:43 +08:00
Xi Lin
e8c66e4597 fix(contracts): fix getL1GasUsed in L1GasPriceOracle (#665)
Co-authored-by: Haichen Shen <shenhaichen@gmail.com>
2023-07-23 04:11:23 -07:00
HAOYUatHZ
de1d9b98ec bump version (#666) 2023-07-22 15:37:13 +08:00
georgehao
58e07a7481 refactor(coordinator): update coordinator orm and layout (#521)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: HAOYUatHZ <haoyu@protonmail.com>
Co-authored-by: colinlyguo <colinlyguo@scroll.io>
2023-07-22 09:24:58 +08:00
colin
3880cdc1af refactor(scroll): update dependencies and format goimports in prover-stats-api module (#662) 2023-07-21 15:03:32 +08:00
Xi Lin
94c557bfed fix(contracts): remove retry with proof in L2ScrollMessenger (#658) 2023-07-21 14:19:01 +08:00
Xi Lin
523cc2cb7e fix(contracts): OZ-L1-L02 Initialization Not Disabled for Implementation Contracts (#639)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 21:14:35 +08:00
Xi Lin
af6d81255c fix(contracts): OZ-L1-M01 Enforced Transactions Signed Off-Chain Are Likely to Fail (#620)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 21:06:12 +08:00
Xi Lin
b5bbb72756 fix(contracts): OZ-L1-L10 Unpinned Compiler Version (#636)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 20:57:43 +08:00
Lawliet-Chan
92c52817e6 fix(prover-stats-api): fix readme (#661)
Co-authored-by: xinran chen <lawliet@xinran-m1x.local>
2023-07-20 18:06:59 +08:00
colin
076cfc1eae refactor(relayer): optimize l1 block schema (#648)
Co-authored-by: georgehao <haohongfan@gmail.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 17:26:43 +08:00
Xi Lin
25e4b6c19d fix(contracts): OZ-L1-L04 Lost Funds in Messenger Contracts (#637)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 17:08:02 +08:00
Péter Garamvölgyi
bae38de0d3 fix(contracts): OZ-L1-L05 Outdated OpenZeppelin Library Version (#622)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: zimpha <zimpha@gmail.com>
2023-07-20 16:54:43 +08:00
Xi Lin
c9f623b12b fix(contracts): OZ-L1-L01 Batch Reverting Can Pause Finalization (#634)
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 16:36:37 +08:00
Xi Lin
3491f0ebff fix(contracts): OZ-L1-L08 Batch Events Lack Information (#624)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 16:24:27 +08:00
Xi Lin
ff4a9e1dd2 fix(contracts): OZ-L1-L07 Lack of Logs on Sensitive Actions (#623)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 16:10:06 +08:00
Xi Lin
f8ec59f7e1 fix(contracts): OZ-L1-M02 Lack of Upgradeability Storage Gaps (#618)
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
2023-07-20 15:52:48 +08:00
279 changed files with 18612 additions and 5583 deletions

View File

@@ -51,7 +51,6 @@ jobs:
uses: actions/checkout@v2
- name: Test
run: |
go get ./...
make test
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3

View File

@@ -1,6 +1,7 @@
package app
import (
"context"
"fmt"
"os"
@@ -9,20 +10,22 @@ import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/mvc"
"github.com/urfave/cli/v2"
"gorm.io/gorm"
"bridge-history-api/config"
"bridge-history-api/controller"
"bridge-history-api/db"
"bridge-history-api/service"
cutils "bridge-history-api/utils"
"scroll-tech/common/database"
)
var (
app *cli.App
app *cli.App
db *gorm.DB
subCtx context.Context
)
var database db.OrmFactory
func pong(ctx iris.Context) {
_, err := ctx.WriteString("pong")
if err != nil {
@@ -33,7 +36,8 @@ func pong(ctx iris.Context) {
func setupQueryByAddressHandler(backendApp *mvc.Application) {
// Register Dependencies.
backendApp.Register(
database,
subCtx,
db,
service.NewHistoryService,
)
@@ -44,7 +48,8 @@ func setupQueryByAddressHandler(backendApp *mvc.Application) {
func setupQueryClaimableHandler(backendApp *mvc.Application) {
// Register Dependencies.
backendApp.Register(
database,
subCtx,
db,
service.NewHistoryService,
)
@@ -54,7 +59,8 @@ func setupQueryClaimableHandler(backendApp *mvc.Application) {
func setupQueryByHashHandler(backendApp *mvc.Application) {
backendApp.Register(
database,
subCtx,
db,
service.NewHistoryService,
)
backendApp.Handle(new(controller.QueryHashController))
@@ -86,15 +92,22 @@ func action(ctx *cli.Context) error {
if err != nil {
log.Crit("failed to load config file", "config file", cfgFile, "error", err)
}
database, err = db.NewOrmFactory(cfg)
dbCfg := &database.Config{
DriverName: cfg.DB.DriverName,
DSN: cfg.DB.DSN,
MaxOpenNum: cfg.DB.MaxOpenNum,
MaxIdleNum: cfg.DB.MaxIdleNum,
}
db, err = database.InitDB(dbCfg)
if err != nil {
log.Crit("can not connect to database", "err", err)
log.Crit("failed to init db", "err", err)
}
defer func() {
if err = database.Close(); err != nil {
log.Error("failed to close database", "err", err)
if deferErr := database.CloseDB(db); deferErr != nil {
log.Error("failed to close db", "err", err)
}
}()
subCtx = ctx.Context
bridgeApp := iris.New()
bridgeApp.UseRouter(corsOptions)
bridgeApp.Get("/ping", pong).Describe("healthcheck")

View File

@@ -14,8 +14,10 @@ import (
"bridge-history-api/config"
"bridge-history-api/crossmsg"
"bridge-history-api/crossmsg/messageproof"
"bridge-history-api/db"
"bridge-history-api/orm"
cutils "bridge-history-api/utils"
"scroll-tech/common/database"
)
var (
@@ -55,9 +57,18 @@ func action(ctx *cli.Context) error {
log.Crit("failed to connect l2 geth", "config file", cfgFile, "error", err)
}
db, err := db.NewOrmFactory(cfg)
dbCfg := &database.Config{
DriverName: cfg.DB.DriverName,
DSN: cfg.DB.DSN,
MaxOpenNum: cfg.DB.MaxOpenNum,
MaxIdleNum: cfg.DB.MaxIdleNum,
}
db, err := database.InitDB(dbCfg)
if err != nil {
log.Crit("failed to init db", "err", err)
}
defer func() {
if deferErr := db.Close(); deferErr != nil {
if deferErr := database.CloseDB(db); deferErr != nil {
log.Error("failed to close db", "err", err)
}
}()
@@ -105,12 +116,14 @@ func action(ctx *cli.Context) error {
go l2crossMsgFetcher.Start()
defer l2crossMsgFetcher.Stop()
CrossMsgOrm := orm.NewCrossMsg(db)
// BlockTimestamp fetcher for l1 and l2
l1BlockTimeFetcher := crossmsg.NewBlockTimestampFetcher(subCtx, cfg.L1.Confirmation, int(cfg.L1.BlockTime), l1client, db.UpdateL1BlockTimestamp, db.GetL1EarliestNoBlockTimestampHeight)
l1BlockTimeFetcher := crossmsg.NewBlockTimestampFetcher(subCtx, cfg.L1.Confirmation, int(cfg.L1.BlockTime), l1client, CrossMsgOrm.UpdateL1BlockTimestamp, CrossMsgOrm.GetL1EarliestNoBlockTimestampHeight)
go l1BlockTimeFetcher.Start()
defer l1BlockTimeFetcher.Stop()
l2BlockTimeFetcher := crossmsg.NewBlockTimestampFetcher(subCtx, cfg.L2.Confirmation, int(cfg.L2.BlockTime), l2client, db.UpdateL2BlockTimestamp, db.GetL2EarliestNoBlockTimestampHeight)
l2BlockTimeFetcher := crossmsg.NewBlockTimestampFetcher(subCtx, cfg.L2.Confirmation, int(cfg.L2.BlockTime), l2client, CrossMsgOrm.UpdateL2BlockTimestamp, CrossMsgOrm.GetL2EarliestNoBlockTimestampHeight)
go l2BlockTimeFetcher.Start()
defer l2BlockTimeFetcher.Stop()

View File

@@ -2,13 +2,14 @@ package app
import (
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
"github.com/urfave/cli/v2"
"gorm.io/gorm"
"bridge-history-api/config"
"bridge-history-api/db"
"bridge-history-api/db/migrate"
"bridge-history-api/orm/migrate"
"bridge-history-api/utils"
"scroll-tech/common/database"
)
func getConfig(ctx *cli.Context) (*config.Config, error) {
@@ -20,14 +21,14 @@ func getConfig(ctx *cli.Context) (*config.Config, error) {
return dbCfg, nil
}
func initDB(dbCfg *config.Config) (*sqlx.DB, error) {
factory, err := db.NewOrmFactory(dbCfg)
if err != nil {
return nil, err
func initDB(dbCfg *config.DBConfig) (*gorm.DB, error) {
cfg := &database.Config{
DriverName: dbCfg.DriverName,
DSN: dbCfg.DSN,
MaxOpenNum: dbCfg.MaxOpenNum,
MaxIdleNum: dbCfg.MaxIdleNum,
}
log.Debug("Got db config from env", "driver name", dbCfg.DB.DriverName, "dsn", dbCfg.DB.DSN)
return factory.GetDB(), nil
return database.InitDB(cfg)
}
// resetDB clean or reset database.
@@ -36,11 +37,15 @@ func resetDB(ctx *cli.Context) error {
if err != nil {
return err
}
db, err := initDB(cfg)
gormDB, err := initDB(cfg.DB)
if err != nil {
return err
}
err = migrate.ResetDB(db.DB)
db, err := gormDB.DB()
if err != nil {
return err
}
err = migrate.ResetDB(db)
if err != nil {
return err
}
@@ -54,12 +59,15 @@ func checkDBStatus(ctx *cli.Context) error {
if err != nil {
return err
}
db, err := initDB(cfg)
gormDB, err := initDB(cfg.DB)
if err != nil {
return err
}
return migrate.Status(db.DB)
db, err := gormDB.DB()
if err != nil {
return err
}
return migrate.Status(db)
}
// dbVersion return the latest version
@@ -68,12 +76,15 @@ func dbVersion(ctx *cli.Context) error {
if err != nil {
return err
}
db, err := initDB(cfg)
gormDB, err := initDB(cfg.DB)
if err != nil {
return err
}
version, err := migrate.Current(db.DB)
db, err := gormDB.DB()
if err != nil {
return err
}
version, err := migrate.Current(db)
log.Info("show database version", "db version", version)
return err
@@ -85,12 +96,15 @@ func migrateDB(ctx *cli.Context) error {
if err != nil {
return err
}
db, err := initDB(cfg)
gormDB, err := initDB(cfg.DB)
if err != nil {
return err
}
return migrate.Migrate(db.DB)
db, err := gormDB.DB()
if err != nil {
return err
}
return migrate.Migrate(db)
}
// rollbackDB rollback db by version
@@ -99,10 +113,14 @@ func rollbackDB(ctx *cli.Context) error {
if err != nil {
return err
}
db, err := initDB(cfg)
gormDB, err := initDB(cfg.DB)
if err != nil {
return err
}
db, err := gormDB.DB()
if err != nil {
return err
}
version := ctx.Int64("version")
return migrate.Rollback(db.DB, &version)
return migrate.Rollback(db, &version)
}

View File

@@ -24,7 +24,7 @@ type QueryClaimableController struct {
// Get defines the http get method behavior for QueryClaimableController
func (c *QueryClaimableController) Get(req model.QueryByAddressRequest) (*model.QueryByAddressResponse, error) {
txs, total, err := c.Service.GetClaimableTxsByAddress(common.HexToAddress(req.Address), int64(req.Offset), int64(req.Limit))
txs, total, err := c.Service.GetClaimableTxsByAddress(common.HexToAddress(req.Address), req.Offset, req.Limit)
if err != nil {
return &model.QueryByAddressResponse{Message: "500", Data: &model.Data{}}, err
}
@@ -38,7 +38,7 @@ func (c *QueryClaimableController) Get(req model.QueryByAddressRequest) (*model.
// Get defines the http get method behavior for QueryAddressController
func (c *QueryAddressController) Get(req model.QueryByAddressRequest) (*model.QueryByAddressResponse, error) {
message, total, err := c.Service.GetTxsByAddress(common.HexToAddress(req.Address), int64(req.Offset), int64(req.Limit))
message, total, err := c.Service.GetTxsByAddress(common.HexToAddress(req.Address), req.Offset, req.Limit)
if err != nil {
return &model.QueryByAddressResponse{Message: "500", Data: &model.Data{}}, err
}

View File

@@ -7,9 +7,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
"bridge-history-api/crossmsg/messageproof"
"bridge-history-api/db"
"bridge-history-api/orm"
"bridge-history-api/utils"
)
@@ -21,12 +22,13 @@ type BatchInfoFetcher struct {
confirmation uint64
blockTimeInSec int
client *ethclient.Client
db db.OrmFactory
db *gorm.DB
rollupOrm *orm.RollupBatch
msgProofUpdater *messageproof.MsgProofUpdater
}
// NewBatchInfoFetcher creates a new BatchInfoFetcher instance
func NewBatchInfoFetcher(ctx context.Context, scrollChainAddr common.Address, batchInfoStartNumber uint64, confirmation uint64, blockTimeInSec int, client *ethclient.Client, db db.OrmFactory, msgProofUpdater *messageproof.MsgProofUpdater) *BatchInfoFetcher {
func NewBatchInfoFetcher(ctx context.Context, scrollChainAddr common.Address, batchInfoStartNumber uint64, confirmation uint64, blockTimeInSec int, client *ethclient.Client, db *gorm.DB, msgProofUpdater *messageproof.MsgProofUpdater) *BatchInfoFetcher {
return &BatchInfoFetcher{
ctx: ctx,
scrollChainAddr: scrollChainAddr,
@@ -35,6 +37,7 @@ func NewBatchInfoFetcher(ctx context.Context, scrollChainAddr common.Address, ba
blockTimeInSec: blockTimeInSec,
client: client,
db: db,
rollupOrm: orm.NewRollupBatch(db),
msgProofUpdater: msgProofUpdater,
}
}
@@ -80,19 +83,20 @@ func (b *BatchInfoFetcher) fetchBatchInfo() error {
log.Error("Can not get latest block number: ", "err", err)
return err
}
latestBatch, err := b.db.GetLatestRollupBatch()
latestBatchHeight, err := b.rollupOrm.GetLatestRollupBatchProcessedHeight(b.ctx)
if err != nil {
log.Error("Can not get latest BatchInfo: ", "err", err)
return err
}
var startHeight uint64
if latestBatch == nil {
if latestBatchHeight == 0 {
log.Info("no batch record in database, start from batchInfoStartNumber", "batchInfoStartNumber", b.batchInfoStartNumber)
startHeight = b.batchInfoStartNumber
} else {
startHeight = latestBatch.CommitHeight + 1
startHeight = latestBatchHeight + 1
}
for from := startHeight; number >= from; from += uint64(fetchLimit) {
to := from + uint64(fetchLimit) - 1
for from := startHeight; number >= from; from += fetchLimit {
to := from + fetchLimit - 1
// number - confirmation can never less than 0 since the for loop condition
// but watch out the overflow
if to > number {

View File

@@ -10,10 +10,10 @@ import (
)
// GetEarliestNoBlockTimestampHeightFunc is a function type that gets the earliest record without block timestamp from database
type GetEarliestNoBlockTimestampHeightFunc func() (uint64, error)
type GetEarliestNoBlockTimestampHeightFunc func(ctx context.Context) (uint64, error)
// UpdateBlockTimestampFunc is a function type that updates block timestamp into database
type UpdateBlockTimestampFunc func(height uint64, timestamp time.Time) error
type UpdateBlockTimestampFunc func(ctx context.Context, height uint64, timestamp time.Time) error
// BlockTimestampFetcher fetches block timestamp from blockchain and saves them to database
type BlockTimestampFetcher struct {
@@ -52,7 +52,7 @@ func (b *BlockTimestampFetcher) Start() {
log.Error("Can not get latest block number", "err", err)
continue
}
startHeight, err := b.getEarliestNoBlockTimestampHeightFunc()
startHeight, err := b.getEarliestNoBlockTimestampHeightFunc(b.ctx)
if err != nil {
log.Error("Can not get latest record without block timestamp", "err", err)
continue
@@ -63,12 +63,12 @@ func (b *BlockTimestampFetcher) Start() {
log.Error("Can not get block by number", "err", err)
break
}
err = b.updateBlockTimestampFunc(height, time.Unix(int64(block.Time), 0))
err = b.updateBlockTimestampFunc(b.ctx, height, time.Unix(int64(block.Time), 0))
if err != nil {
log.Error("Can not update blockTimestamp into DB ", "err", err)
break
}
height, err = b.getEarliestNoBlockTimestampHeightFunc()
height, err = b.getEarliestNoBlockTimestampHeightFunc(b.ctx)
if err != nil {
log.Error("Can not get latest record without block timestamp", "err", err)
break

View File

@@ -12,9 +12,9 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/modern-go/reflect2"
"gorm.io/gorm"
"bridge-history-api/config"
"bridge-history-api/db"
"bridge-history-api/utils"
)
@@ -22,7 +22,7 @@ import (
type MsgFetcher struct {
ctx context.Context
config *config.LayerConfig
db db.OrmFactory
db *gorm.DB
client *ethclient.Client
worker *FetchEventWorker
reorgHandling ReorgHandling
@@ -34,7 +34,7 @@ type MsgFetcher struct {
}
// NewMsgFetcher creates a new MsgFetcher instance
func NewMsgFetcher(ctx context.Context, config *config.LayerConfig, db db.OrmFactory, client *ethclient.Client, worker *FetchEventWorker, addressList []common.Address, reorg ReorgHandling) (*MsgFetcher, error) {
func NewMsgFetcher(ctx context.Context, config *config.LayerConfig, db *gorm.DB, client *ethclient.Client, worker *FetchEventWorker, addressList []common.Address, reorg ReorgHandling) (*MsgFetcher, error) {
msgFetcher := &MsgFetcher{
ctx: ctx,
config: config,
@@ -120,22 +120,23 @@ func (c *MsgFetcher) forwardFetchAndSaveMissingEvents(confirmation uint64) {
log.Error(fmt.Sprintf("%s: invalid get/fetch function", c.worker.Name))
return
}
processedHeight, err := c.worker.G(c.db)
processedHeight, err := c.worker.G(c.ctx, c.db)
if err != nil {
log.Error(fmt.Sprintf("%s: can not get latest processed block height", c.worker.Name))
}
log.Info(fmt.Sprintf("%s: ", c.worker.Name), "height", processedHeight)
if processedHeight <= 0 || processedHeight < int64(c.config.StartHeight) {
processedHeight = int64(c.config.StartHeight)
if processedHeight <= 0 || processedHeight < c.config.StartHeight {
processedHeight = c.config.StartHeight
} else {
processedHeight++
}
for from := processedHeight; from <= int64(number); from += fetchLimit {
for from := processedHeight; from <= number; from += fetchLimit {
to := from + fetchLimit - 1
if to > int64(number) {
to = int64(number)
if to > number {
to = number
}
err := c.worker.F(c.ctx, c.client, c.db, from, to, c.addressList)
// watch for overflow here, tho its unlikely to happen
err := c.worker.F(c.ctx, c.client, c.db, int64(from), int64(to), c.addressList)
if err != nil {
log.Error(fmt.Sprintf("%s: failed!", c.worker.Name), "err", err)
break
@@ -191,7 +192,7 @@ func (c *MsgFetcher) fetchMissingLatestHeaders() {
log.Crit("Can not get safe number during reorg, quit the process", "err", err)
}
// clear all our saved data, because no data is safe now
err = c.reorgHandling(c.ctx, int64(num), c.db)
err = c.reorgHandling(c.ctx, num, c.db)
// if handling success then we can update the cachedHeaders
if err == nil {
c.cachedHeaders = c.cachedHeaders[:0]
@@ -200,7 +201,7 @@ func (c *MsgFetcher) fetchMissingLatestHeaders() {
c.reorgEndCh <- struct{}{}
return
}
err = c.reorgHandling(c.ctx, c.cachedHeaders[index].Number.Int64(), c.db)
err = c.reorgHandling(c.ctx, c.cachedHeaders[index].Number.Uint64(), c.db)
// if handling success then we can update the cachedHeaders
if err == nil {
c.cachedHeaders = c.cachedHeaders[:index+1]

View File

@@ -8,23 +8,24 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
backendabi "bridge-history-api/abi"
"bridge-history-api/db"
"bridge-history-api/orm"
"bridge-history-api/utils"
)
// Todo : read from config
var (
// the number of blocks fetch per round
fetchLimit = int64(3000)
fetchLimit = uint64(3000)
)
// FetchAndSave is a function type that fetches events from blockchain and saves them to database
type FetchAndSave func(ctx context.Context, client *ethclient.Client, database db.OrmFactory, from int64, to int64, addressList []common.Address) error
type FetchAndSave func(ctx context.Context, client *ethclient.Client, database *gorm.DB, from int64, to int64, addressList []common.Address) error
// GetLatestProcessed is a function type that gets the latest processed block height from database
type GetLatestProcessed func(db db.OrmFactory) (int64, error)
type GetLatestProcessed func(ctx context.Context, db *gorm.DB) (uint64, error)
// FetchEventWorker defines worker with fetch and save function, processed number getter, and name
type FetchEventWorker struct {
@@ -34,13 +35,15 @@ type FetchEventWorker struct {
}
// GetLatestL1ProcessedHeight get L1 the latest processed height
func GetLatestL1ProcessedHeight(db db.OrmFactory) (int64, error) {
crossHeight, err := db.GetLatestL1ProcessedHeight()
func GetLatestL1ProcessedHeight(ctx context.Context, db *gorm.DB) (uint64, error) {
l1CrossMsgOrm := orm.NewCrossMsg(db)
relayedOrm := orm.NewRelayedMsg(db)
crossHeight, err := l1CrossMsgOrm.GetLatestL1ProcessedHeight(ctx)
if err != nil {
log.Error("failed to get L1 cross message processed height: ", "err", err)
return 0, err
}
relayedHeight, err := db.GetLatestRelayedHeightOnL1()
relayedHeight, err := relayedOrm.GetLatestRelayedHeightOnL1(ctx)
if err != nil {
log.Error("failed to get L1 relayed message processed height: ", "err", err)
return 0, err
@@ -52,18 +55,21 @@ func GetLatestL1ProcessedHeight(db db.OrmFactory) (int64, error) {
}
// GetLatestL2ProcessedHeight get L2 latest processed height
func GetLatestL2ProcessedHeight(db db.OrmFactory) (int64, error) {
crossHeight, err := db.GetLatestL2ProcessedHeight()
func GetLatestL2ProcessedHeight(ctx context.Context, db *gorm.DB) (uint64, error) {
l2CrossMsgOrm := orm.NewCrossMsg(db)
relayedOrm := orm.NewRelayedMsg(db)
l2SentMsgOrm := orm.NewL2SentMsg(db)
crossHeight, err := l2CrossMsgOrm.GetLatestL2ProcessedHeight(ctx)
if err != nil {
log.Error("failed to get L2 cross message processed height", "err", err)
return 0, err
}
relayedHeight, err := db.GetLatestRelayedHeightOnL2()
relayedHeight, err := relayedOrm.GetLatestRelayedHeightOnL2(ctx)
if err != nil {
log.Error("failed to get L2 relayed message processed height", "err", err)
return 0, err
}
l2SentHeight, err := db.GetLatestSentMsgHeightOnL2()
l2SentHeight, err := l2SentMsgOrm.GetLatestSentMsgHeightOnL2(ctx)
if err != nil {
log.Error("failed to get L2 sent message processed height", "err", err)
return 0, err
@@ -79,7 +85,9 @@ func GetLatestL2ProcessedHeight(db db.OrmFactory) (int64, error) {
}
// L1FetchAndSaveEvents fetch and save events on L1
func L1FetchAndSaveEvents(ctx context.Context, client *ethclient.Client, database db.OrmFactory, from int64, to int64, addrList []common.Address) error {
func L1FetchAndSaveEvents(ctx context.Context, client *ethclient.Client, db *gorm.DB, from int64, to int64, addrList []common.Address) error {
l1CrossMsgOrm := orm.NewCrossMsg(db)
relayedOrm := orm.NewRelayedMsg(db)
query := geth.FilterQuery{
FromBlock: big.NewInt(from), // inclusive
ToBlock: big.NewInt(to), // inclusive
@@ -105,41 +113,28 @@ func L1FetchAndSaveEvents(ctx context.Context, client *ethclient.Client, databas
log.Error("l1FetchAndSaveEvents: Failed to parse cross msg event logs", "err", err)
return err
}
dbTx, err := database.Beginx()
if err != nil {
log.Error("l2FetchAndSaveEvents: Failed to begin db transaction", "err", err)
return err
}
err = database.BatchInsertL1CrossMsgDBTx(dbTx, depositL1CrossMsgs)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
err = db.Transaction(func(tx *gorm.DB) error {
if txErr := l1CrossMsgOrm.InsertL1CrossMsg(ctx, depositL1CrossMsgs, tx); txErr != nil {
log.Error("l1FetchAndSaveEvents: Failed to insert cross msg event logs", "err", txErr)
return txErr
}
log.Crit("l1FetchAndSaveEvents: Failed to insert cross msg event logs", "err", err)
}
err = database.BatchInsertRelayedMsgDBTx(dbTx, relayedMsg)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
if txErr := relayedOrm.InsertRelayedMsg(ctx, relayedMsg, tx); txErr != nil {
log.Error("l1FetchAndSaveEvents: Failed to insert relayed msg event logs", "err", txErr)
return txErr
}
log.Crit("l1FetchAndSaveEvents: Failed to insert relayed message event logs", "err", err)
}
err = dbTx.Commit()
return nil
})
if err != nil {
// if we can not insert into DB, there must something wrong, need a on-call member handle the dababase manually
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Error("l1FetchAndSaveEvents: Failed to commit db transaction", "err", err)
return err
log.Crit("l2FetchAndSaveEvents: Failed to finish transaction", "err", err)
}
return nil
return err
}
// L2FetchAndSaveEvents fetche and save events on L2
func L2FetchAndSaveEvents(ctx context.Context, client *ethclient.Client, database db.OrmFactory, from int64, to int64, addrList []common.Address) error {
func L2FetchAndSaveEvents(ctx context.Context, client *ethclient.Client, db *gorm.DB, from int64, to int64, addrList []common.Address) error {
l2CrossMsgOrm := orm.NewCrossMsg(db)
relayedOrm := orm.NewRelayedMsg(db)
l2SentMsgOrm := orm.NewL2SentMsg(db)
query := geth.FilterQuery{
FromBlock: big.NewInt(from), // inclusive
ToBlock: big.NewInt(to), // inclusive
@@ -166,50 +161,32 @@ func L2FetchAndSaveEvents(ctx context.Context, client *ethclient.Client, databas
return err
}
dbTx, err := database.Beginx()
if err != nil {
log.Error("l2FetchAndSaveEvents: Failed to begin db transaction", "err", err)
return err
}
err = database.BatchInsertL2CrossMsgDBTx(dbTx, depositL2CrossMsgs)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
err = db.Transaction(func(tx *gorm.DB) error {
if txErr := l2CrossMsgOrm.InsertL2CrossMsg(ctx, depositL2CrossMsgs, tx); txErr != nil {
log.Error("l2FetchAndSaveEvents: Failed to insert cross msg event logs", "err", txErr)
return txErr
}
log.Crit("l2FetchAndSaveEvents: Failed to insert cross msg event logs", "err", err)
}
err = database.BatchInsertRelayedMsgDBTx(dbTx, relayedMsg)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
if txErr := relayedOrm.InsertRelayedMsg(ctx, relayedMsg, tx); txErr != nil {
log.Error("l2FetchAndSaveEvents: Failed to insert relayed message event logs", "err", txErr)
return txErr
}
log.Crit("l2FetchAndSaveEvents: Failed to insert relayed message event logs", "err", err)
}
err = database.BatchInsertL2SentMsgDBTx(dbTx, l2SentMsgs)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
if txErr := l2SentMsgOrm.InsertL2SentMsg(ctx, l2SentMsgs, tx); txErr != nil {
log.Error("l2FetchAndSaveEvents: Failed to insert l2 sent message", "err", txErr)
return txErr
}
log.Crit("l2FetchAndSaveEvents: Failed to insert l2 sent message", "err", err)
}
err = dbTx.Commit()
return nil
})
if err != nil {
// if we can not insert into DB, there must something wrong, need a on-call member handle the dababase manually
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Error("l2FetchAndSaveEvents: Failed to commit db transaction", "err", err)
return err
log.Crit("l2FetchAndSaveEvents: Failed to begin db transaction", "err", err)
}
return nil
return err
}
// FetchAndSaveBatchIndex fetche and save batch index
func FetchAndSaveBatchIndex(ctx context.Context, client *ethclient.Client, database db.OrmFactory, from int64, to int64, scrollChainAddr common.Address) error {
func FetchAndSaveBatchIndex(ctx context.Context, client *ethclient.Client, db *gorm.DB, from int64, to int64, scrollChainAddr common.Address) error {
rollupBatchOrm := orm.NewRollupBatch(db)
query := geth.FilterQuery{
FromBlock: big.NewInt(from), // inclusive
ToBlock: big.NewInt(to), // inclusive
@@ -228,26 +205,9 @@ func FetchAndSaveBatchIndex(ctx context.Context, client *ethclient.Client, datab
log.Error("FetchAndSaveBatchIndex: Failed to parse batch commit msg event logs", "err", err)
return err
}
dbTx, err := database.Beginx()
if err != nil {
log.Error("FetchAndSaveBatchIndex: Failed to begin db transaction", "err", err)
return err
}
err = database.BatchInsertRollupBatchDBTx(dbTx, rollupBatches)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Crit("FetchAndSaveBatchIndex: Failed to insert batch commit msg event logs", "err", err)
}
err = dbTx.Commit()
if err != nil {
// if we can not insert into DB, there must something wrong, need a on-call member handle the dababase manually
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Error("FetchAndSaveBatchIndex: Failed to commit db transaction", "err", err)
return err
if txErr := rollupBatchOrm.InsertRollupBatch(ctx, rollupBatches); txErr != nil {
log.Crit("FetchAndSaveBatchIndex: Failed to insert batch commit msg event logs", "err", txErr)
return txErr
}
return nil
}

View File

@@ -2,30 +2,32 @@ package messageproof
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
"bridge-history-api/db"
"bridge-history-api/db/orm"
"bridge-history-api/orm"
)
// MsgProofUpdater is used to update message proof in db
type MsgProofUpdater struct {
ctx context.Context
db db.OrmFactory
db *gorm.DB
l2SentMsgOrm *orm.L2SentMsg
rollupOrm *orm.RollupBatch
withdrawTrie *WithdrawTrie
}
// NewMsgProofUpdater new MsgProofUpdater instance
func NewMsgProofUpdater(ctx context.Context, confirmations uint64, startBlock uint64, db db.OrmFactory) *MsgProofUpdater {
func NewMsgProofUpdater(ctx context.Context, confirmations uint64, startBlock uint64, db *gorm.DB) *MsgProofUpdater {
return &MsgProofUpdater{
ctx: ctx,
db: db,
l2SentMsgOrm: orm.NewL2SentMsg(db),
rollupOrm: orm.NewRollupBatch(db),
withdrawTrie: NewWithdrawTrie(),
}
}
@@ -42,7 +44,7 @@ func (m *MsgProofUpdater) Start() {
tick.Stop()
return
case <-tick.C:
latestBatch, err := m.db.GetLatestRollupBatch()
latestBatch, err := m.rollupOrm.GetLatestRollupBatch(m.ctx)
if err != nil {
log.Warn("MsgProofUpdater: Can not get latest RollupBatch: ", "err", err)
continue
@@ -50,7 +52,7 @@ func (m *MsgProofUpdater) Start() {
if latestBatch == nil {
continue
}
latestBatchIndexWithProof, err := m.db.GetLatestL2SentMsgBatchIndex()
latestBatchIndexWithProof, err := m.l2SentMsgOrm.GetLatestL2SentMsgBatchIndex(m.ctx)
if err != nil {
log.Error("MsgProofUpdater: Can not get latest L2SentMsgBatchIndex: ", "err", err)
continue
@@ -62,7 +64,7 @@ func (m *MsgProofUpdater) Start() {
start = uint64(latestBatchIndexWithProof) + 1
}
for i := start; i <= latestBatch.BatchIndex; i++ {
batch, err := m.db.GetRollupBatchByIndex(i)
batch, err := m.rollupOrm.GetRollupBatchByIndex(m.ctx, i)
if err != nil {
log.Error("MsgProofUpdater: Can not get RollupBatch: ", "err", err, "index", i)
break
@@ -111,8 +113,8 @@ func (m *MsgProofUpdater) initialize(ctx context.Context) {
func (m *MsgProofUpdater) initializeWithdrawTrie() error {
var batch *orm.RollupBatch
firstMsg, err := m.db.GetL2SentMessageByNonce(0)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
firstMsg, err := m.l2SentMsgOrm.GetL2SentMessageByNonce(m.ctx, 0)
if err != nil {
return fmt.Errorf("failed to get first l2 message: %v", err)
}
// no l2 message
@@ -123,7 +125,7 @@ func (m *MsgProofUpdater) initializeWithdrawTrie() error {
}
// if no batch, return and wait for next try round
batch, err = m.db.GetLatestRollupBatch()
batch, err = m.rollupOrm.GetLatestRollupBatch(m.ctx)
if err != nil {
return fmt.Errorf("failed to get latest batch: %v", err)
}
@@ -135,7 +137,7 @@ func (m *MsgProofUpdater) initializeWithdrawTrie() error {
batchIndex := batch.BatchIndex
for {
var msg *orm.L2SentMsg
msg, err = m.db.GetLatestL2SentMsgLEHeight(batch.EndBlockNumber)
msg, err = m.l2SentMsgOrm.GetLatestL2SentMsgLEHeight(m.ctx, batch.EndBlockNumber)
if err != nil {
log.Warn("failed to get l2 sent message less than height", "endBlocknum", batch.EndBlockNumber, "err", err)
}
@@ -159,8 +161,8 @@ func (m *MsgProofUpdater) initializeWithdrawTrie() error {
// iterate for next batch
batchIndex--
batch, err = m.db.GetRollupBatchByIndex(batchIndex)
if err != nil {
batch, err = m.rollupOrm.GetRollupBatchByIndex(m.ctx, batchIndex)
if err != nil || batch == nil {
return fmt.Errorf("failed to get block batch %v: %v", batchIndex, err)
}
}
@@ -191,36 +193,26 @@ func (m *MsgProofUpdater) updateMsgProof(msgs []*orm.L2SentMsg, proofs [][]byte,
if len(msgs) != len(proofs) {
return fmt.Errorf("illegal state: len(msgs) != len(proofs)")
}
dbTx, err := m.db.Beginx()
err := m.db.Transaction(func(tx *gorm.DB) error {
for i, msg := range msgs {
proofHex := common.Bytes2Hex(proofs[i])
log.Debug("updateMsgProof", "msgHash", msg.MsgHash, "batchIndex", batchIndex, "proof", proofHex)
if err := m.l2SentMsgOrm.UpdateL2MessageProof(m.ctx, msg.MsgHash, proofHex, batchIndex, tx); err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
for i, msg := range msgs {
proofHex := common.Bytes2Hex(proofs[i])
log.Debug("updateMsgProof", "msgHash", msg.MsgHash, "batchIndex", batchIndex, "proof", proofHex)
if dbTxErr := m.db.UpdateL2MessageProofInDBTx(m.ctx, dbTx, msg.MsgHash, proofHex, batchIndex); dbTxErr != nil {
if err := dbTx.Rollback(); err != nil {
log.Error("dbTx.Rollback()", "err", err)
}
return dbTxErr
}
}
if dbTxErr := dbTx.Commit(); dbTxErr != nil {
if err := dbTx.Rollback(); err != nil {
log.Error("dbTx.Rollback()", "err", err)
}
return dbTxErr
}
return nil
}
// appendL2Messages will append all messages between firstBlock and lastBlock (both inclusive) to withdrawTrie and compute corresponding merkle proof of each message.
func (m *MsgProofUpdater) appendL2Messages(firstBlock, lastBlock uint64) ([]*orm.L2SentMsg, [][]byte, error) {
var msgProofs [][]byte
messages, err := m.db.GetL2SentMsgMsgHashByHeightRange(firstBlock, lastBlock)
messages, err := m.l2SentMsgOrm.GetL2SentMsgMsgHashByHeightRange(m.ctx, firstBlock, lastBlock)
if err != nil {
log.Error("GetL2SentMsgMsgHashByHeightRange failed", "error", err, "firstBlock", firstBlock, "lastBlock", lastBlock)
return messages, msgProofs, err

View File

@@ -6,12 +6,13 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
"bridge-history-api/db"
"bridge-history-api/orm"
)
// ReorgHandling handles reorg function type
type ReorgHandling func(ctx context.Context, reorgHeight int64, db db.OrmFactory) error
type ReorgHandling func(ctx context.Context, reorgHeight uint64, db *gorm.DB) error
func reverseArray(arr []*types.Header) []*types.Header {
for i := 0; i < len(arr)/2; i++ {
@@ -60,73 +61,48 @@ func BackwardFindReorgBlock(ctx context.Context, headers []*types.Header, client
}
// L1ReorgHandling handles l1 reorg
func L1ReorgHandling(ctx context.Context, reorgHeight int64, db db.OrmFactory) error {
dbTx, err := db.Beginx()
if err != nil {
log.Crit("begin db tx failed", "err", err)
}
err = db.DeleteL1CrossMsgAfterHeightDBTx(dbTx, reorgHeight)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
func L1ReorgHandling(ctx context.Context, reorgHeight uint64, db *gorm.DB) error {
l1CrossMsgOrm := orm.NewCrossMsg(db)
relayedOrm := orm.NewRelayedMsg(db)
err := db.Transaction(func(tx *gorm.DB) error {
if err := l1CrossMsgOrm.DeleteL1CrossMsgAfterHeight(ctx, reorgHeight, tx); err != nil {
log.Error("delete l1 cross msg from height", "height", reorgHeight, "err", err)
return err
}
log.Crit("delete l1 cross msg from height", "height", reorgHeight, "err", err)
}
err = db.DeleteL1RelayedHashAfterHeightDBTx(dbTx, reorgHeight)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
if err := relayedOrm.DeleteL1RelayedHashAfterHeight(ctx, reorgHeight, tx); err != nil {
log.Error("delete l1 relayed msg from height", "height", reorgHeight, "err", err)
return err
}
log.Crit("delete l1 relayed hash from height", "height", reorgHeight, "err", err)
}
err = dbTx.Commit()
return nil
})
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Error("commit tx failed", "err", err)
return err
log.Crit("l1 reorg handling failed", "err", err)
}
return nil
return err
}
// L2ReorgHandling handles l2 reorg
func L2ReorgHandling(ctx context.Context, reorgHeight int64, db db.OrmFactory) error {
dbTx, err := db.Beginx()
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
func L2ReorgHandling(ctx context.Context, reorgHeight uint64, db *gorm.DB) error {
l2CrossMsgOrm := orm.NewCrossMsg(db)
relayedOrm := orm.NewRelayedMsg(db)
l2SentMsgOrm := orm.NewL2SentMsg(db)
err := db.Transaction(func(tx *gorm.DB) error {
if err := l2CrossMsgOrm.DeleteL2CrossMsgFromHeight(ctx, reorgHeight, tx); err != nil {
log.Error("delete l2 cross msg from height", "height", reorgHeight, "err", err)
return err
}
log.Crit("begin db tx failed", "err", err)
}
err = db.DeleteL2CrossMsgFromHeightDBTx(dbTx, reorgHeight)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
if err := relayedOrm.DeleteL2RelayedHashAfterHeight(ctx, reorgHeight, tx); err != nil {
log.Error("delete l2 relayed msg from height", "height", reorgHeight, "err", err)
return err
}
log.Crit("delete l2 cross msg from height", "height", reorgHeight, "err", err)
}
err = db.DeleteL2RelayedHashAfterHeightDBTx(dbTx, reorgHeight)
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
if err := l2SentMsgOrm.DeleteL2SentMsgAfterHeight(ctx, reorgHeight, tx); err != nil {
log.Error("delete l2 sent msg from height", "height", reorgHeight, "err", err)
return err
}
log.Crit("delete l2 relayed hash from height", "height", reorgHeight, "err", err)
}
err = db.DeleteL2SentMsgAfterHeightDBTx(dbTx, reorgHeight)
return nil
})
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Crit("delete l2 sent msg from height", "height", reorgHeight, "err", err)
log.Crit("l2 reorg handling failed", "err", err)
}
err = dbTx.Commit()
if err != nil {
if rollBackErr := dbTx.Rollback(); rollBackErr != nil {
log.Error("dbTx Rollback failed", "err", rollBackErr)
}
log.Error("commit tx failed", "err", err)
return err
}
return nil
return err
}

View File

@@ -1,71 +0,0 @@
package orm
import (
"database/sql"
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
)
type rollupBatchOrm struct {
db *sqlx.DB
}
// RollupBatch is the struct for rollup_batch table
type RollupBatch struct {
ID uint64 `json:"id" db:"id"`
BatchIndex uint64 `json:"batch_index" db:"batch_index"`
BatchHash string `json:"batch_hash" db:"batch_hash"`
CommitHeight uint64 `json:"commit_height" db:"commit_height"`
StartBlockNumber uint64 `json:"start_block_number" db:"start_block_number"`
EndBlockNumber uint64 `json:"end_block_number" db:"end_block_number"`
}
// NewRollupBatchOrm create an NewRollupBatchOrm instance
func NewRollupBatchOrm(db *sqlx.DB) RollupBatchOrm {
return &rollupBatchOrm{db: db}
}
func (b *rollupBatchOrm) BatchInsertRollupBatchDBTx(dbTx *sqlx.Tx, batches []*RollupBatch) error {
if len(batches) == 0 {
return nil
}
var err error
batchMaps := make([]map[string]interface{}, len(batches))
for i, batch := range batches {
batchMaps[i] = map[string]interface{}{
"commit_height": batch.CommitHeight,
"batch_index": batch.BatchIndex,
"batch_hash": batch.BatchHash,
"start_block_number": batch.StartBlockNumber,
"end_block_number": batch.EndBlockNumber,
}
}
_, err = dbTx.NamedExec(`insert into rollup_batch(commit_height, batch_index, batch_hash, start_block_number, end_block_number) values(:commit_height, :batch_index, :batch_hash, :start_block_number, :end_block_number);`, batchMaps)
if err != nil {
log.Error("BatchInsertRollupBatchDBTx: failed to insert batch event msgs", "err", err)
return err
}
return nil
}
func (b *rollupBatchOrm) GetLatestRollupBatch() (*RollupBatch, error) {
result := &RollupBatch{}
row := b.db.QueryRowx(`SELECT id, batch_index, commit_height, batch_hash, start_block_number, end_block_number FROM rollup_batch ORDER BY batch_index DESC LIMIT 1;`)
if err := row.StructScan(result); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return result, nil
}
func (b *rollupBatchOrm) GetRollupBatchByIndex(index uint64) (*RollupBatch, error) {
result := &RollupBatch{}
row := b.db.QueryRowx(`SELECT id, batch_index, batch_hash, commit_height, start_block_number, end_block_number FROM rollup_batch WHERE batch_index = $1;`, index)
if err := row.StructScan(result); err != nil {
return nil, err
}
return result, nil
}

View File

@@ -1,132 +0,0 @@
package orm
import (
"context"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/jmoiron/sqlx"
)
// AssetType can be ETH/ERC20/ERC1155/ERC721
type AssetType int
// MsgType can be layer1/layer2 msg
type MsgType int
func (a AssetType) String() string {
switch a {
case ETH:
return "ETH"
case ERC20:
return "ERC20"
case ERC1155:
return "ERC1155"
case ERC721:
return "ERC721"
}
return "Unknown Asset Type"
}
const (
// ETH = 0
ETH AssetType = iota
// ERC20 = 1
ERC20
// ERC721 = 2
ERC721
// ERC1155 = 3
ERC1155
)
const (
// UnknownMsg = 0
UnknownMsg MsgType = iota
// Layer1Msg = 1
Layer1Msg
// Layer2Msg = 2
Layer2Msg
)
// CrossMsg represents a cross message from layer 1 to layer 2
type CrossMsg struct {
ID uint64 `json:"id" db:"id"`
MsgHash string `json:"msg_hash" db:"msg_hash"`
Height uint64 `json:"height" db:"height"`
Sender string `json:"sender" db:"sender"`
Target string `json:"target" db:"target"`
Amount string `json:"amount" db:"amount"`
Layer1Hash string `json:"layer1_hash" db:"layer1_hash"`
Layer2Hash string `json:"layer2_hash" db:"layer2_hash"`
Layer1Token string `json:"layer1_token" db:"layer1_token"`
Layer2Token string `json:"layer2_token" db:"layer2_token"`
TokenIDs string `json:"token_ids" db:"token_ids"`
TokenAmounts string `json:"token_amounts" db:"token_amounts"`
Asset int `json:"asset" db:"asset"`
MsgType int `json:"msg_type" db:"msg_type"`
Timestamp *time.Time `json:"timestamp" db:"block_timestamp"`
CreatedAt *time.Time `json:"created_at" db:"created_at"`
UpdatedAt *time.Time `json:"updated_at" db:"updated_at"`
DeletedAt *time.Time `json:"deleted_at" db:"deleted_at"`
}
// L1CrossMsgOrm provides operations on l1_cross_message table
type L1CrossMsgOrm interface {
GetL1CrossMsgByHash(l1Hash common.Hash) (*CrossMsg, error)
GetL1CrossMsgsByAddress(sender common.Address) ([]*CrossMsg, error)
BatchInsertL1CrossMsgDBTx(dbTx *sqlx.Tx, messages []*CrossMsg) error
// UpdateL1CrossMsgHashDBTx invoked when SentMessage event is received
UpdateL1CrossMsgHashDBTx(ctx context.Context, dbTx *sqlx.Tx, l1Hash, msgHash common.Hash) error
UpdateL1CrossMsgHash(ctx context.Context, l1Hash, msgHash common.Hash) error
GetLatestL1ProcessedHeight() (int64, error)
DeleteL1CrossMsgAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error
UpdateL1BlockTimestamp(height uint64, timestamp time.Time) error
GetL1EarliestNoBlockTimestampHeight() (uint64, error)
}
// L2CrossMsgOrm provides operations on cross_message table
type L2CrossMsgOrm interface {
GetL2CrossMsgByHash(l2Hash common.Hash) (*CrossMsg, error)
GetL2CrossMsgByAddress(sender common.Address) ([]*CrossMsg, error)
BatchInsertL2CrossMsgDBTx(dbTx *sqlx.Tx, messages []*CrossMsg) error
// UpdateL2CrossMsgHashDBTx invoked when SentMessage event is received
UpdateL2CrossMsgHashDBTx(ctx context.Context, dbTx *sqlx.Tx, l2Hash, msgHash common.Hash) error
UpdateL2CrossMsgHash(ctx context.Context, l2Hash, msgHash common.Hash) error
GetLatestL2ProcessedHeight() (int64, error)
DeleteL2CrossMsgFromHeightDBTx(dbTx *sqlx.Tx, height int64) error
UpdateL2BlockTimestamp(height uint64, timestamp time.Time) error
GetL2EarliestNoBlockTimestampHeight() (uint64, error)
GetL2CrossMsgByMsgHashList(msgHashList []string) ([]*CrossMsg, error)
}
// RelayedMsgOrm provides operations on relayed_msg table
type RelayedMsgOrm interface {
BatchInsertRelayedMsgDBTx(dbTx *sqlx.Tx, messages []*RelayedMsg) error
GetRelayedMsgByHash(msgHash string) (*RelayedMsg, error)
GetLatestRelayedHeightOnL1() (int64, error)
GetLatestRelayedHeightOnL2() (int64, error)
DeleteL1RelayedHashAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error
DeleteL2RelayedHashAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error
}
// L2SentMsgOrm provides operations on l2_sent_msg table
type L2SentMsgOrm interface {
BatchInsertL2SentMsgDBTx(dbTx *sqlx.Tx, messages []*L2SentMsg) error
GetL2SentMsgByHash(l2Hash string) (*L2SentMsg, error)
GetLatestSentMsgHeightOnL2() (int64, error)
GetL2SentMessageByNonce(nonce uint64) (*L2SentMsg, error)
GetLatestL2SentMsgLEHeight(endBlockNumber uint64) (*L2SentMsg, error)
GetL2SentMsgMsgHashByHeightRange(startHeight, endHeight uint64) ([]*L2SentMsg, error)
UpdateL2MessageProofInDBTx(ctx context.Context, dbTx *sqlx.Tx, msgHash string, proof string, batchIndex uint64) error
GetLatestL2SentMsgBatchIndex() (int64, error)
GetClaimableL2SentMsgByAddressWithOffset(address string, offset int64, limit int64) ([]*L2SentMsg, error)
GetClaimableL2SentMsgByAddressTotalNum(address string) (uint64, error)
DeleteL2SentMsgAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error
}
// RollupBatchOrm provides operations on rollup_batch table
type RollupBatchOrm interface {
GetLatestRollupBatch() (*RollupBatch, error)
GetRollupBatchByIndex(index uint64) (*RollupBatch, error)
BatchInsertRollupBatchDBTx(dbTx *sqlx.Tx, messages []*RollupBatch) error
}

View File

@@ -1,148 +0,0 @@
package orm
import (
"context"
"database/sql"
"errors"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
)
type l1CrossMsgOrm struct {
db *sqlx.DB
}
// NewL1CrossMsgOrm create an NewL1CrossMsgOrm instance
func NewL1CrossMsgOrm(db *sqlx.DB) L1CrossMsgOrm {
return &l1CrossMsgOrm{db: db}
}
func (l *l1CrossMsgOrm) GetL1CrossMsgByHash(l1Hash common.Hash) (*CrossMsg, error) {
result := &CrossMsg{}
row := l.db.QueryRowx(`SELECT * FROM cross_message WHERE layer1_hash = $1 AND msg_type = $2 AND deleted_at IS NULL;`, l1Hash.String(), Layer1Msg)
if err := row.StructScan(result); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}
return result, nil
}
// GetL1CrossMsgsByAddress returns all layer1 cross messages under given address
// Warning: return empty slice if no data found
func (l *l1CrossMsgOrm) GetL1CrossMsgsByAddress(sender common.Address) ([]*CrossMsg, error) {
var results []*CrossMsg
rows, err := l.db.Queryx(`SELECT * FROM cross_message WHERE sender = $1 AND msg_type = 1 AND deleted_at IS NULL;`, sender.String(), Layer1Msg)
if err != nil {
return nil, err
}
defer func() {
if err = rows.Close(); err != nil {
log.Error("failed to close rows", "err", err)
}
}()
for rows.Next() {
msg := &CrossMsg{}
if err = rows.StructScan(msg); err != nil {
break
}
results = append(results, msg)
}
if len(results) == 0 && errors.Is(err, sql.ErrNoRows) {
} else if err != nil {
return nil, err
}
return results, nil
}
func (l *l1CrossMsgOrm) BatchInsertL1CrossMsgDBTx(dbTx *sqlx.Tx, messages []*CrossMsg) error {
if len(messages) == 0 {
return nil
}
var err error
messageMaps := make([]map[string]interface{}, len(messages))
for i, msg := range messages {
messageMaps[i] = map[string]interface{}{
"height": msg.Height,
"sender": msg.Sender,
"target": msg.Target,
"amount": msg.Amount,
"asset": msg.Asset,
"msg_hash": msg.MsgHash,
"layer1_hash": msg.Layer1Hash,
"layer1_token": msg.Layer1Token,
"layer2_token": msg.Layer2Token,
"token_ids": msg.TokenIDs,
"msg_type": Layer1Msg,
}
}
_, err = dbTx.NamedExec(`insert into cross_message(height, sender, target, amount, asset, msg_hash, layer1_hash, layer1_token, layer2_token, token_ids, msg_type) values(:height, :sender, :target, :amount, :asset, :msg_hash, :layer1_hash, :layer1_token, :layer2_token, :token_ids, :msg_type);`, messageMaps)
if err != nil {
log.Error("BatchInsertL1CrossMsgDBTx: failed to insert l1 cross msgs", "err", err)
return err
}
return nil
}
// UpdateL1CrossMsgHashDBTx update l1 cross msg hash in db, no need to check msg_type since layer1_hash wont be empty if its layer1 msg
func (l *l1CrossMsgOrm) UpdateL1CrossMsgHashDBTx(ctx context.Context, dbTx *sqlx.Tx, l1Hash, msgHash common.Hash) error {
if _, err := dbTx.ExecContext(ctx, l.db.Rebind("update public.cross_message set msg_hash = ? where layer1_hash = ? AND deleted_at IS NULL;"), msgHash.String(), l1Hash.String()); err != nil {
return err
}
return nil
}
func (l *l1CrossMsgOrm) UpdateL1CrossMsgHash(ctx context.Context, l1Hash, msgHash common.Hash) error {
if _, err := l.db.ExecContext(ctx, l.db.Rebind("update public.l1_cross_message set msg_hash = ? where layer1_hash = ? AND deleted_at IS NULL;"), msgHash.String(), l1Hash.String()); err != nil {
return err
}
return nil
}
func (l *l1CrossMsgOrm) GetLatestL1ProcessedHeight() (int64, error) {
row := l.db.QueryRowx(`SELECT height FROM cross_message WHERE msg_type = $1 AND deleted_at IS NULL ORDER BY id DESC LIMIT 1;`, Layer1Msg)
var result sql.NullInt64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows || !result.Valid {
return -1, nil
}
return 0, err
}
if result.Valid {
return result.Int64, nil
}
return 0, nil
}
func (l *l1CrossMsgOrm) DeleteL1CrossMsgAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error {
if _, err := l.db.Exec(`UPDATE cross_message SET deleted_at = current_timestamp WHERE height > $1 AND msg_type = $2;`, height, Layer1Msg); err != nil {
return err
}
return nil
}
func (l *l1CrossMsgOrm) UpdateL1BlockTimestamp(height uint64, timestamp time.Time) error {
if _, err := l.db.Exec(`UPDATE cross_message SET block_timestamp = $1 where height = $2 AND msg_type = $3 AND deleted_at IS NULL`, timestamp, height, Layer1Msg); err != nil {
return err
}
return nil
}
func (l *l1CrossMsgOrm) GetL1EarliestNoBlockTimestampHeight() (uint64, error) {
row := l.db.QueryRowx(`SELECT height FROM cross_message WHERE block_timestamp IS NULL AND msg_type = $1 AND deleted_at IS NULL ORDER BY height ASC LIMIT 1;`, Layer1Msg)
var result uint64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows {
return 0, nil
}
return 0, err
}
return result, nil
}

View File

@@ -1,177 +0,0 @@
package orm
import (
"context"
"database/sql"
"errors"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
)
type l2CrossMsgOrm struct {
db *sqlx.DB
}
// NewL2CrossMsgOrm create an NewL2CrossMsgOrm instance
func NewL2CrossMsgOrm(db *sqlx.DB) L2CrossMsgOrm {
return &l2CrossMsgOrm{db: db}
}
func (l *l2CrossMsgOrm) GetL2CrossMsgByHash(l2Hash common.Hash) (*CrossMsg, error) {
result := &CrossMsg{}
row := l.db.QueryRowx(`SELECT * FROM cross_message WHERE layer2_hash = $1 AND deleted_at IS NULL;`, l2Hash.String())
if err := row.StructScan(result); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}
return result, nil
}
// GetL2CrossMsgByAddress returns all layer2 cross messages under given address
// Warning: return empty slice if no data found
func (l *l2CrossMsgOrm) GetL2CrossMsgByAddress(sender common.Address) ([]*CrossMsg, error) {
var results []*CrossMsg
rows, err := l.db.Queryx(`SELECT * FROM cross_message WHERE sender = $1 AND msg_type = $2 AND deleted_at IS NULL;`, sender.String(), Layer2Msg)
if err != nil {
return nil, err
}
defer func() {
if err = rows.Close(); err != nil {
log.Error("failed to close rows", "err", err)
}
}()
for rows.Next() {
msg := &CrossMsg{}
if err = rows.StructScan(msg); err != nil {
break
}
results = append(results, msg)
}
if len(results) == 0 && errors.Is(err, sql.ErrNoRows) {
// log.Warn("no unprocessed layer1 messages in db", "err", err)
} else if err != nil {
return nil, err
}
return results, nil
}
func (l *l2CrossMsgOrm) DeleteL2CrossMsgFromHeightDBTx(dbTx *sqlx.Tx, height int64) error {
_, err := dbTx.Exec(`UPDATE cross_message SET deleted_at = current_timestamp where height > $1 AND msg_type = $2 ;`, height, Layer2Msg)
if err != nil {
log.Error("DeleteL1CrossMsgAfterHeightDBTx: failed to delete", "height", height, "err", err)
return err
}
return nil
}
func (l *l2CrossMsgOrm) BatchInsertL2CrossMsgDBTx(dbTx *sqlx.Tx, messages []*CrossMsg) error {
if len(messages) == 0 {
return nil
}
var err error
messageMaps := make([]map[string]interface{}, len(messages))
for i, msg := range messages {
messageMaps[i] = map[string]interface{}{
"height": msg.Height,
"sender": msg.Sender,
"target": msg.Target,
"asset": msg.Asset,
"msg_hash": msg.MsgHash,
"layer2_hash": msg.Layer2Hash,
"layer1_token": msg.Layer1Token,
"layer2_token": msg.Layer2Token,
"token_ids": msg.TokenIDs,
"amount": msg.Amount,
"msg_type": Layer2Msg,
}
}
_, err = dbTx.NamedExec(`insert into cross_message(height, sender, target, asset, msg_hash, layer2_hash, layer1_token, layer2_token, token_ids, amount, msg_type) values(:height, :sender, :target, :asset, :msg_hash, :layer2_hash, :layer1_token, :layer2_token, :token_ids, :amount, :msg_type);`, messageMaps)
if err != nil {
log.Error("BatchInsertL2CrossMsgDBTx: failed to insert l2 cross msgs", "err", err)
return err
}
return nil
}
func (l *l2CrossMsgOrm) UpdateL2CrossMsgHashDBTx(ctx context.Context, dbTx *sqlx.Tx, l2Hash, msgHash common.Hash) error {
if _, err := dbTx.ExecContext(ctx, l.db.Rebind("update cross_message set msg_hash = ? where layer2_hash = ? AND deleted_at IS NULL;"), msgHash.String(), l2Hash.String()); err != nil {
return err
}
return nil
}
func (l *l2CrossMsgOrm) UpdateL2CrossMsgHash(ctx context.Context, l2Hash, msgHash common.Hash) error {
if _, err := l.db.ExecContext(ctx, l.db.Rebind("update cross_message set msg_hash = ? where layer2_hash = ? AND deleted_at IS NULL;"), msgHash.String(), l2Hash.String()); err != nil {
return err
}
return nil
}
func (l *l2CrossMsgOrm) GetLatestL2ProcessedHeight() (int64, error) {
row := l.db.QueryRowx(`SELECT height FROM cross_message WHERE msg_type = $1 AND deleted_at IS NULL ORDER BY id DESC LIMIT 1;`, Layer2Msg)
var result sql.NullInt64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows || !result.Valid {
return -1, nil
}
return 0, err
}
if result.Valid {
return result.Int64, nil
}
return 0, nil
}
func (l *l2CrossMsgOrm) UpdateL2BlockTimestamp(height uint64, timestamp time.Time) error {
if _, err := l.db.Exec(`UPDATE cross_message SET block_timestamp = $1 where height = $2 AND msg_type = $3 AND deleted_at IS NULL`, timestamp, height, Layer2Msg); err != nil {
return err
}
return nil
}
func (l *l2CrossMsgOrm) GetL2EarliestNoBlockTimestampHeight() (uint64, error) {
row := l.db.QueryRowx(`SELECT height FROM cross_message WHERE block_timestamp IS NULL AND msg_type = $1 AND deleted_at IS NULL ORDER BY height ASC LIMIT 1;`, Layer2Msg)
var result uint64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows {
return 0, nil
}
return 0, err
}
return result, nil
}
func (l *l2CrossMsgOrm) GetL2CrossMsgByMsgHashList(msgHashList []string) ([]*CrossMsg, error) {
var results []*CrossMsg
rows, err := l.db.Queryx(`SELECT * FROM cross_message WHERE msg_hash = ANY($1) AND msg_type = $2 AND deleted_at IS NULL;`, pq.Array(msgHashList), Layer2Msg)
if err != nil {
return nil, err
}
defer func() {
if err = rows.Close(); err != nil {
log.Error("failed to close rows", "err", err)
}
}()
for rows.Next() {
msg := &CrossMsg{}
if err = rows.StructScan(msg); err != nil {
break
}
results = append(results, msg)
}
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, err
}
if len(results) == 0 {
log.Debug("no L2CrossMsg under given msg hashes", "msg hash list", msgHashList)
}
return results, nil
}

View File

@@ -1,189 +0,0 @@
package orm
import (
"context"
"database/sql"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
)
// L2SentMsg defines the struct for l2_sent_msg table record
type L2SentMsg struct {
ID uint64 `json:"id" db:"id"`
OriginalSender string `json:"original_sender" db:"original_sender"`
TxHash string `json:"tx_hash" db:"tx_hash"`
MsgHash string `json:"msg_hash" db:"msg_hash"`
Sender string `json:"sender" db:"sender"`
Target string `json:"target" db:"target"`
Value string `json:"value" db:"value"`
Height uint64 `json:"height" db:"height"`
Nonce uint64 `json:"nonce" db:"nonce"`
BatchIndex uint64 `json:"batch_index" db:"batch_index"`
MsgProof string `json:"msg_proof" db:"msg_proof"`
MsgData string `json:"msg_data" db:"msg_data"`
CreatedAt *time.Time `json:"created_at" db:"created_at"`
UpdatedAt *time.Time `json:"updated_at" db:"updated_at"`
DeletedAt *time.Time `json:"deleted_at" db:"deleted_at"`
}
type l2SentMsgOrm struct {
db *sqlx.DB
}
// NewL2SentMsgOrm create an NewRollupBatchOrm instance
func NewL2SentMsgOrm(db *sqlx.DB) L2SentMsgOrm {
return &l2SentMsgOrm{db: db}
}
func (l *l2SentMsgOrm) GetL2SentMsgByHash(msgHash string) (*L2SentMsg, error) {
result := &L2SentMsg{}
row := l.db.QueryRowx(`SELECT * FROM l2_sent_msg WHERE msg_hash = $1 AND deleted_at IS NULL;`, msgHash)
if err := row.StructScan(result); err != nil {
return nil, err
}
return result, nil
}
func (l *l2SentMsgOrm) BatchInsertL2SentMsgDBTx(dbTx *sqlx.Tx, messages []*L2SentMsg) error {
if len(messages) == 0 {
return nil
}
var err error
messageMaps := make([]map[string]interface{}, len(messages))
for i, msg := range messages {
messageMaps[i] = map[string]interface{}{
"original_sender": msg.OriginalSender,
"tx_hash": msg.TxHash,
"sender": msg.Sender,
"target": msg.Target,
"value": msg.Value,
"msg_hash": msg.MsgHash,
"height": msg.Height,
"nonce": msg.Nonce,
"batch_index": msg.BatchIndex,
"msg_proof": msg.MsgProof,
"msg_data": msg.MsgData,
}
}
_, err = dbTx.NamedExec(`insert into l2_sent_msg(original_sender, tx_hash, sender, target, value, msg_hash, height, nonce, batch_index, msg_proof, msg_data) values(:original_sender, :tx_hash, :sender, :target, :value, :msg_hash, :height, :nonce, :batch_index, :msg_proof, :msg_data);`, messageMaps)
if err != nil {
log.Error("BatchInsertL2SentMsgDBTx: failed to insert l2 sent msgs", "err", err)
return err
}
return err
}
func (l *l2SentMsgOrm) GetLatestSentMsgHeightOnL2() (int64, error) {
row := l.db.QueryRow(`SELECT height FROM l2_sent_msg WHERE deleted_at IS NULL ORDER BY nonce DESC LIMIT 1;`)
var result sql.NullInt64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows || !result.Valid {
return -1, nil
}
return 0, err
}
if result.Valid {
return result.Int64, nil
}
return 0, nil
}
func (l *l2SentMsgOrm) UpdateL2MessageProofInDBTx(ctx context.Context, dbTx *sqlx.Tx, msgHash string, proof string, batchIndex uint64) error {
if _, err := dbTx.ExecContext(ctx, l.db.Rebind("update l2_sent_msg set msg_proof = ?, batch_index = ? where msg_hash = ? AND deleted_at IS NULL;"), proof, batchIndex, msgHash); err != nil {
return err
}
return nil
}
func (l *l2SentMsgOrm) GetLatestL2SentMsgBatchIndex() (int64, error) {
row := l.db.QueryRow(`SELECT batch_index FROM l2_sent_msg WHERE batch_index != 0 AND deleted_at IS NULL ORDER BY batch_index DESC LIMIT 1;`)
var result sql.NullInt64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows || !result.Valid {
return -1, nil
}
return -1, err
}
if result.Valid {
return result.Int64, nil
}
return -1, nil
}
func (l *l2SentMsgOrm) GetL2SentMsgMsgHashByHeightRange(startHeight, endHeight uint64) ([]*L2SentMsg, error) {
var results []*L2SentMsg
rows, err := l.db.Queryx(`SELECT * FROM l2_sent_msg WHERE height >= $1 AND height <= $2 AND deleted_at IS NULL ORDER BY nonce ASC;`, startHeight, endHeight)
if err != nil {
return nil, err
}
defer func() {
if err = rows.Close(); err != nil {
log.Error("failed to close rows", "err", err)
}
}()
for rows.Next() {
msg := &L2SentMsg{}
if err = rows.StructScan(msg); err != nil {
break
}
results = append(results, msg)
}
return results, err
}
func (l *l2SentMsgOrm) GetL2SentMessageByNonce(nonce uint64) (*L2SentMsg, error) {
result := &L2SentMsg{}
row := l.db.QueryRowx(`SELECT * FROM l2_sent_msg WHERE nonce = $1 AND deleted_at IS NULL;`, nonce)
err := row.StructScan(result)
if err != nil {
return nil, err
}
return result, nil
}
func (l *l2SentMsgOrm) GetLatestL2SentMsgLEHeight(endBlockNumber uint64) (*L2SentMsg, error) {
result := &L2SentMsg{}
row := l.db.QueryRowx(`select * from l2_sent_msg where height <= $1 AND deleted_at IS NULL order by nonce desc limit 1`, endBlockNumber)
err := row.StructScan(result)
if err != nil {
return nil, err
}
return result, nil
}
func (l *l2SentMsgOrm) DeleteL2SentMsgAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error {
_, err := dbTx.Exec(`UPDATE l2_sent_msg SET deleted_at = current_timestamp WHERE height > $1;`, height)
return err
}
func (l *l2SentMsgOrm) GetClaimableL2SentMsgByAddressWithOffset(address string, offset int64, limit int64) ([]*L2SentMsg, error) {
var results []*L2SentMsg
rows, err := l.db.Queryx(`SELECT * FROM l2_sent_msg WHERE id NOT IN (SELECT l2_sent_msg.id FROM l2_sent_msg INNER JOIN relayed_msg ON l2_sent_msg.msg_hash = relayed_msg.msg_hash WHERE l2_sent_msg.deleted_at IS NULL AND relayed_msg.deleted_at IS NULL) AND (original_sender=$1 OR sender = $1) ORDER BY id DESC LIMIT $2 OFFSET $3;`, address, limit, offset)
if err != nil {
return nil, err
}
defer func() {
if err = rows.Close(); err != nil {
log.Error("failed to close rows", "err", err)
}
}()
for rows.Next() {
msg := &L2SentMsg{}
if err = rows.StructScan(msg); err != nil {
break
}
results = append(results, msg)
}
return results, err
}
func (l *l2SentMsgOrm) GetClaimableL2SentMsgByAddressTotalNum(address string) (uint64, error) {
var count uint64
row := l.db.QueryRowx(`SELECT COUNT(*) FROM l2_sent_msg WHERE id NOT IN (SELECT l2_sent_msg.id FROM l2_sent_msg INNER JOIN relayed_msg ON l2_sent_msg.msg_hash = relayed_msg.msg_hash WHERE l2_sent_msg.deleted_at IS NULL AND relayed_msg.deleted_at IS NULL) AND (original_sender=$1 OR sender = $1);`, address)
if err := row.Scan(&count); err != nil {
return 0, err
}
return count, nil
}

View File

@@ -1,100 +0,0 @@
package orm
import (
"database/sql"
"errors"
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
)
// RelayedMsg is the struct for relayed_msg table
type RelayedMsg struct {
MsgHash string `json:"msg_hash" db:"msg_hash"`
Height uint64 `json:"height" db:"height"`
Layer1Hash string `json:"layer1_hash" db:"layer1_hash"`
Layer2Hash string `json:"layer2_hash" db:"layer2_hash"`
}
type relayedMsgOrm struct {
db *sqlx.DB
}
// NewRelayedMsgOrm create an NewRelayedMsgOrm instance
func NewRelayedMsgOrm(db *sqlx.DB) RelayedMsgOrm {
return &relayedMsgOrm{db: db}
}
func (l *relayedMsgOrm) BatchInsertRelayedMsgDBTx(dbTx *sqlx.Tx, messages []*RelayedMsg) error {
if len(messages) == 0 {
return nil
}
var err error
messageMaps := make([]map[string]interface{}, len(messages))
for i, msg := range messages {
messageMaps[i] = map[string]interface{}{
"msg_hash": msg.MsgHash,
"height": msg.Height,
"layer1_hash": msg.Layer1Hash,
"layer2_hash": msg.Layer2Hash,
}
}
_, err = dbTx.NamedExec(`insert into relayed_msg(msg_hash, height, layer1_hash, layer2_hash) values(:msg_hash, :height, :layer1_hash, :layer2_hash);`, messageMaps)
if err != nil {
log.Error("BatchInsertRelayedMsgDBTx: failed to insert relayed msgs", "err", err)
return err
}
return nil
}
func (l *relayedMsgOrm) GetRelayedMsgByHash(msgHash string) (*RelayedMsg, error) {
result := &RelayedMsg{}
row := l.db.QueryRowx(`SELECT msg_hash, height, layer1_hash, layer2_hash FROM relayed_msg WHERE msg_hash = $1 AND deleted_at IS NULL;`, msgHash)
if err := row.StructScan(result); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}
return result, nil
}
func (l *relayedMsgOrm) GetLatestRelayedHeightOnL1() (int64, error) {
row := l.db.QueryRow(`SELECT height FROM relayed_msg WHERE layer1_hash != '' AND deleted_at IS NULL ORDER BY height DESC LIMIT 1;`)
var result sql.NullInt64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows || !result.Valid {
return -1, nil
}
return 0, err
}
if result.Valid {
return result.Int64, nil
}
return 0, nil
}
func (l *relayedMsgOrm) GetLatestRelayedHeightOnL2() (int64, error) {
row := l.db.QueryRow(`SELECT height FROM relayed_msg WHERE layer2_hash != '' AND deleted_at IS NULL ORDER BY height DESC LIMIT 1;`)
var result sql.NullInt64
if err := row.Scan(&result); err != nil {
if err == sql.ErrNoRows || !result.Valid {
return -1, nil
}
return 0, err
}
if result.Valid {
return result.Int64, nil
}
return 0, nil
}
func (l *relayedMsgOrm) DeleteL1RelayedHashAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error {
_, err := dbTx.Exec(`UPDATE relayed_msg SET deleted_at = current_timestamp WHERE height > $1 AND layer1_hash != '';`, height)
return err
}
func (l *relayedMsgOrm) DeleteL2RelayedHashAfterHeightDBTx(dbTx *sqlx.Tx, height int64) error {
_, err := dbTx.Exec(`UPDATE relayed_msg SET deleted_at = current_timestamp WHERE height > $1 AND layer2_hash != '';`, height)
return err
}

View File

@@ -1,103 +0,0 @@
package db
import (
"database/sql"
"errors"
"github.com/ethereum/go-ethereum/log"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq" //nolint:golint
"bridge-history-api/config"
"bridge-history-api/db/orm"
)
// OrmFactory include all ormFactory interface
type OrmFactory interface {
orm.L1CrossMsgOrm
orm.L2CrossMsgOrm
orm.RelayedMsgOrm
orm.L2SentMsgOrm
orm.RollupBatchOrm
GetTotalCrossMsgCountByAddress(sender string) (uint64, error)
GetCrossMsgsByAddressWithOffset(sender string, offset int64, limit int64) ([]*orm.CrossMsg, error)
GetDB() *sqlx.DB
Beginx() (*sqlx.Tx, error)
Close() error
}
type ormFactory struct {
orm.L1CrossMsgOrm
orm.L2CrossMsgOrm
orm.RelayedMsgOrm
orm.L2SentMsgOrm
orm.RollupBatchOrm
*sqlx.DB
}
// NewOrmFactory create an ormFactory factory include all ormFactory interface
func NewOrmFactory(cfg *config.Config) (OrmFactory, error) {
// Initialize sql/sqlx
db, err := sqlx.Open(cfg.DB.DriverName, cfg.DB.DSN)
if err != nil {
return nil, err
}
db.SetMaxOpenConns(cfg.DB.MaxOpenNum)
db.SetMaxIdleConns(cfg.DB.MaxIdleNum)
if err = db.Ping(); err != nil {
return nil, err
}
return &ormFactory{
L1CrossMsgOrm: orm.NewL1CrossMsgOrm(db),
L2CrossMsgOrm: orm.NewL2CrossMsgOrm(db),
RelayedMsgOrm: orm.NewRelayedMsgOrm(db),
L2SentMsgOrm: orm.NewL2SentMsgOrm(db),
RollupBatchOrm: orm.NewRollupBatchOrm(db),
DB: db,
}, nil
}
func (o *ormFactory) GetDB() *sqlx.DB {
return o.DB
}
func (o *ormFactory) Beginx() (*sqlx.Tx, error) {
return o.DB.Beginx()
}
func (o *ormFactory) GetTotalCrossMsgCountByAddress(sender string) (uint64, error) {
var count uint64
row := o.DB.QueryRowx(`SELECT COUNT(*) FROM cross_message WHERE sender = $1 AND deleted_at IS NULL;`, sender)
if err := row.Scan(&count); err != nil {
return 0, err
}
return count, nil
}
func (o *ormFactory) GetCrossMsgsByAddressWithOffset(sender string, offset int64, limit int64) ([]*orm.CrossMsg, error) {
para := sender
var results []*orm.CrossMsg
rows, err := o.DB.Queryx(`SELECT * FROM cross_message WHERE sender = $1 AND deleted_at IS NULL ORDER BY block_timestamp DESC NULLS FIRST, id DESC LIMIT $2 OFFSET $3;`, para, limit, offset)
if err != nil || rows == nil {
return nil, err
}
defer func() {
if err = rows.Close(); err != nil {
log.Error("failed to close rows", "err", err)
}
}()
for rows.Next() {
msg := &orm.CrossMsg{}
if err = rows.StructScan(msg); err != nil {
break
}
results = append(results, msg)
}
if len(results) == 0 && errors.Is(err, sql.ErrNoRows) {
} else if err != nil {
return nil, err
}
return results, nil
}

View File

@@ -5,19 +5,18 @@ go 1.19
require (
github.com/ethereum/go-ethereum v1.12.0
github.com/iris-contrib/middleware/cors v0.0.0-20230531125531-980d3a09a458
github.com/jmoiron/sqlx v1.3.5
github.com/kataras/iris/v12 v12.2.0
github.com/lib/pq v1.10.7
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.18
github.com/mattn/go-isatty v0.0.19
github.com/modern-go/reflect2 v1.0.2
github.com/pressly/goose/v3 v3.7.0
github.com/stretchr/testify v1.8.2
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
github.com/stretchr/testify v1.8.3
github.com/urfave/cli/v2 v2.25.7
gorm.io/gorm v1.25.2
)
require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
@@ -44,7 +43,7 @@ require (
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/docker v20.10.21+incompatible // indirect
github.com/docker/docker v23.0.6+incompatible // indirect
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect
github.com/ethereum/c-kzg-4844 v0.2.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
@@ -54,7 +53,6 @@ require (
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
@@ -78,6 +76,8 @@ require (
github.com/iris-contrib/go.uuid v2.0.0+incompatible // indirect
github.com/iris-contrib/schema v0.0.6 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kataras/blocks v0.0.7 // indirect
github.com/kataras/golog v0.1.8 // indirect
@@ -91,10 +91,9 @@ require (
github.com/mailgun/raymond/v2 v2.0.48 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mediocregopher/radix/v3 v3.8.1 // indirect
github.com/microcosm-cc/bluemonday v1.0.23 // indirect
github.com/microcosm-cc/bluemonday v1.0.25 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.0 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
@@ -134,16 +133,16 @@ require (
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yosssi/ace v0.0.5 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.8.0 // indirect
golang.org/x/tools v0.11.0 // indirect
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
google.golang.org/protobuf v1.29.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect

View File

@@ -1,8 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
@@ -97,8 +97,8 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
github.com/docker/docker v20.10.21+incompatible h1:UTLdBmHk3bEY+w8qeO5KttOhy6OmXWsl/FEet9Uswog=
github.com/docker/docker v20.10.21+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v23.0.6+incompatible h1:aBD4np894vatVX99UTx/GyOUOK4uEcROwA3+bQhEcoU=
github.com/docker/docker v23.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
@@ -143,9 +143,6 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
@@ -251,8 +248,10 @@ github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
@@ -302,9 +301,6 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
@@ -326,15 +322,12 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@@ -342,8 +335,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i
github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M=
github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/microcosm-cc/bluemonday v1.0.23 h1:SMZe2IGa0NuHvnVNAZ+6B38gsTbi5e4sViiWJyDDqFY=
github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4=
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
@@ -456,18 +449,14 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b h1:u49mjRnygnB34h8OKbnNJFVUtWSKIKb1KukdV8bILUM=
github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
@@ -488,8 +477,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
@@ -537,8 +526,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
@@ -551,7 +540,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -574,8 +563,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -585,8 +574,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -628,8 +617,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -638,8 +627,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@@ -660,8 +649,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -692,8 +681,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0=
google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -724,6 +713,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=

View File

@@ -0,0 +1,94 @@
package orm
import (
"context"
"fmt"
"time"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
)
// RollupBatch is the struct for rollup_batch table
type RollupBatch struct {
db *gorm.DB `gorm:"column:-"`
ID uint64 `json:"id" gorm:"column:id"`
BatchIndex uint64 `json:"batch_index" gorm:"column:batch_index"`
BatchHash string `json:"batch_hash" gorm:"column:batch_hash"`
CommitHeight uint64 `json:"commit_height" gorm:"column:commit_height"`
StartBlockNumber uint64 `json:"start_block_number" gorm:"column:start_block_number"`
EndBlockNumber uint64 `json:"end_block_number" gorm:"column:end_block_number"`
CreatedAt *time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt *time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"column:deleted_at;default:NULL"`
}
// NewRollupBatch create an RollupBatch instance
func NewRollupBatch(db *gorm.DB) *RollupBatch {
return &RollupBatch{db: db}
}
// TableName returns the table name for the Batch model.
func (*RollupBatch) TableName() string {
return "rollup_batch"
}
// GetLatestRollupBatchProcessedHeight return latest processed height from rollup_batch table
func (r *RollupBatch) GetLatestRollupBatchProcessedHeight(ctx context.Context) (uint64, error) {
var result RollupBatch
err := r.db.WithContext(ctx).Unscoped().Select("commit_height").Order("id desc").First(&result).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("RollupBatch.GetLatestRollupBatchProcessedHeight error: %w", err)
}
return result.CommitHeight, nil
}
// GetLatestRollupBatch return the latest rollup batch in db
func (r *RollupBatch) GetLatestRollupBatch(ctx context.Context) (*RollupBatch, error) {
var result RollupBatch
err := r.db.WithContext(ctx).Model(&RollupBatch{}).Where("batch_hash is not NULL").Order("batch_index desc").First(&result).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, fmt.Errorf("RollupBatch.GetLatestRollupBatch error: %w", err)
}
return &result, nil
}
// GetRollupBatchByIndex return the rollup batch by index
func (r *RollupBatch) GetRollupBatchByIndex(ctx context.Context, index uint64) (*RollupBatch, error) {
var result RollupBatch
err := r.db.WithContext(ctx).Model(&RollupBatch{}).Where("batch_index = ?", index).First(&result).Error
if err != nil {
return nil, fmt.Errorf("RollupBatch.GetRollupBatchByIndex error: %w", err)
}
return &result, nil
}
// InsertRollupBatch batch insert rollup batch into db and return the transaction
func (r *RollupBatch) InsertRollupBatch(ctx context.Context, batches []*RollupBatch, dbTx ...*gorm.DB) error {
if len(batches) == 0 {
return nil
}
db := r.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
err := db.WithContext(ctx).Model(&RollupBatch{}).Create(&batches).Error
if err != nil {
batchIndexes := make([]uint64, 0, len(batches))
heights := make([]uint64, 0, len(batches))
for _, batch := range batches {
batchIndexes = append(batchIndexes, batch.BatchIndex)
heights = append(heights, batch.CommitHeight)
}
log.Error("failed to insert rollup batch", "batchIndexes", batchIndexes, "heights", heights)
return fmt.Errorf("RollupBatch.InsertRollupBatch error: %w", err)
}
return nil
}

View File

@@ -0,0 +1,370 @@
package orm
import (
"context"
"errors"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
)
// AssetType can be ETH/ERC20/ERC1155/ERC721
type AssetType int
// MsgType can be layer1/layer2 msg
type MsgType int
func (a AssetType) String() string {
switch a {
case ETH:
return "ETH"
case ERC20:
return "ERC20"
case ERC1155:
return "ERC1155"
case ERC721:
return "ERC721"
}
return "Unknown Asset Type"
}
const (
// ETH = 0
ETH AssetType = iota
// ERC20 = 1
ERC20
// ERC721 = 2
ERC721
// ERC1155 = 3
ERC1155
)
const (
// UnknownMsg = 0
UnknownMsg MsgType = iota
// Layer1Msg = 1
Layer1Msg
// Layer2Msg = 2
Layer2Msg
)
// CrossMsg represents a cross message from layer 1 to layer 2
type CrossMsg struct {
db *gorm.DB `gorm:"column:-"`
ID uint64 `json:"id" gorm:"column:id"`
MsgHash string `json:"msg_hash" gorm:"column:msg_hash"`
Height uint64 `json:"height" gorm:"column:height"`
Sender string `json:"sender" gorm:"column:sender"`
Target string `json:"target" gorm:"column:target"`
Amount string `json:"amount" gorm:"column:amount"`
Layer1Hash string `json:"layer1_hash" gorm:"column:layer1_hash;default:''"`
Layer2Hash string `json:"layer2_hash" gorm:"column:layer2_hash;default:''"`
Layer1Token string `json:"layer1_token" gorm:"column:layer1_token;default:''"`
Layer2Token string `json:"layer2_token" gorm:"column:layer2_token;default:''"`
TokenIDs string `json:"token_ids" gorm:"column:token_ids;default:''"`
TokenAmounts string `json:"token_amounts" gorm:"column:token_amounts;default:''"`
Asset int `json:"asset" gorm:"column:asset"`
MsgType int `json:"msg_type" gorm:"column:msg_type"`
Timestamp *time.Time `json:"timestamp" gorm:"column:block_timestamp;default;NULL"`
CreatedAt *time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt *time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"column:deleted_at;default:NULL"`
}
// TableName returns the table name for the CrossMsg model.
func (*CrossMsg) TableName() string {
return "cross_message"
}
// NewCrossMsg returns a new instance of CrossMsg.
func NewCrossMsg(db *gorm.DB) *CrossMsg {
return &CrossMsg{db: db}
}
// L1 Cross Msgs Operations
// GetL1CrossMsgByHash returns layer1 cross message by given hash
func (c *CrossMsg) GetL1CrossMsgByHash(ctx context.Context, l1Hash common.Hash) (*CrossMsg, error) {
var result CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).Where("layer1_hash = ? AND msg_type = ?", l1Hash.String(), Layer1Msg).First(&result).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, fmt.Errorf("CrossMsg.GetL1CrossMsgByHash error: %w", err)
}
return &result, nil
}
// GetLatestL1ProcessedHeight returns the latest processed height of layer1 cross messages
func (c *CrossMsg) GetLatestL1ProcessedHeight(ctx context.Context) (uint64, error) {
var result CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).Where("msg_type = ?", Layer1Msg).
Select("height").
Order("id DESC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("CrossMsg.GetLatestL1ProcessedHeight error: %w", err)
}
return result.Height, nil
}
// GetL1EarliestNoBlockTimestampHeight returns the earliest layer1 cross message height which has no block timestamp
func (c *CrossMsg) GetL1EarliestNoBlockTimestampHeight(ctx context.Context) (uint64, error) {
var result CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("block_timestamp IS NULL AND msg_type = ?", Layer1Msg).
Select("height").
Order("height ASC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("CrossMsg.GetL1EarliestNoBlockTimestampHeight error: %w", err)
}
return result.Height, nil
}
// InsertL1CrossMsg batch insert layer1 cross messages into db
func (c *CrossMsg) InsertL1CrossMsg(ctx context.Context, messages []*CrossMsg, dbTx ...*gorm.DB) error {
if len(messages) == 0 {
return nil
}
db := c.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&CrossMsg{}).Create(&messages).Error
if err != nil {
l1hashes := make([]string, 0, len(messages))
heights := make([]uint64, 0, len(messages))
for _, msg := range messages {
l1hashes = append(l1hashes, msg.Layer1Hash)
heights = append(heights, msg.Height)
}
log.Error("failed to insert l1 cross messages", "l1hashes", l1hashes, "heights", heights, "err", err)
return fmt.Errorf("CrossMsg.InsertL1CrossMsg error: %w", err)
}
return nil
}
// UpdateL1CrossMsgHash update l1 cross msg hash in db, no need to check msg_type since layer1_hash wont be empty if its layer1 msg
func (c *CrossMsg) UpdateL1CrossMsgHash(ctx context.Context, l1Hash, msgHash common.Hash, dbTx ...*gorm.DB) error {
db := c.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := c.db.Model(&CrossMsg{}).Where("layer1_hash = ?", l1Hash.Hex()).Update("msg_hash", msgHash.Hex()).Error
if err != nil {
return fmt.Errorf("CrossMsg.UpdateL1CrossMsgHash error: %w", err)
}
return nil
}
// UpdateL1BlockTimestamp update layer1 block timestamp
func (c *CrossMsg) UpdateL1BlockTimestamp(ctx context.Context, height uint64, timestamp time.Time) error {
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("height = ? AND msg_type = ?", height, Layer1Msg).
Update("block_timestamp", timestamp).Error
if err != nil {
return fmt.Errorf("CrossMsg.UpdateL1BlockTimestamp error: %w", err)
}
return err
}
// DeleteL1CrossMsgAfterHeight soft delete layer1 cross messages after given height
func (c *CrossMsg) DeleteL1CrossMsgAfterHeight(ctx context.Context, height uint64, dbTx ...*gorm.DB) error {
db := c.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Delete(&CrossMsg{}, "height > ? AND msg_type = ?", height, Layer1Msg).Error
if err != nil {
return fmt.Errorf("CrossMsg.DeleteL1CrossMsgAfterHeight error: %w", err)
}
return nil
}
// L2 Cross Msgs Operations
// 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(), Layer1Msg).First(&result).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, fmt.Errorf("CrossMsg.GetL2CrossMsgByHash error: %w", err)
}
return &result, nil
}
// GetLatestL2ProcessedHeight returns the latest processed height of layer2 cross messages
func (c *CrossMsg) GetLatestL2ProcessedHeight(ctx context.Context) (uint64, error) {
var result CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Select("height").
Where("msg_type = ?", Layer2Msg).
Order("id DESC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("CrossMsg.GetLatestL2ProcessedHeight error: %w", err)
}
return result.Height, nil
}
// GetL2CrossMsgByMsgHashList returns layer2 cross messages under given msg hashes
func (c *CrossMsg) GetL2CrossMsgByMsgHashList(ctx context.Context, msgHashList []string) ([]*CrossMsg, error) {
var results []*CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("msg_hash IN (?) AND msg_type = ?", msgHashList, Layer2Msg).
Find(&results).
Error
if err != nil {
return nil, fmt.Errorf("CrossMsg.GetL2CrossMsgByMsgHashList error: %w", err)
}
if len(results) == 0 {
log.Debug("no CrossMsg under given msg hashes", "msg hash list", msgHashList)
}
return results, nil
}
// GetL2EarliestNoBlockTimestampHeight returns the earliest layer2 cross message height which has no block timestamp
func (c *CrossMsg) GetL2EarliestNoBlockTimestampHeight(ctx context.Context) (uint64, error) {
var result CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("block_timestamp IS NULL AND msg_type = ?", Layer2Msg).
Select("height").
Order("height ASC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("CrossMsg.GetL2EarliestNoBlockTimestampHeight error: %w", err)
}
return result.Height, nil
}
// InsertL2CrossMsg batch insert layer2 cross messages
func (c *CrossMsg) InsertL2CrossMsg(ctx context.Context, messages []*CrossMsg, dbTx ...*gorm.DB) error {
if len(messages) == 0 {
return nil
}
db := c.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&CrossMsg{}).Create(&messages).Error
if err != nil {
l2hashes := make([]string, 0, len(messages))
heights := make([]uint64, 0, len(messages))
for _, msg := range messages {
l2hashes = append(l2hashes, msg.Layer2Hash)
heights = append(heights, msg.Height)
}
log.Error("failed to insert l2 cross messages", "l2hashes", l2hashes, "heights", heights, "err", err)
return fmt.Errorf("CrossMsg.InsertL2CrossMsg error: %w", err)
}
return nil
}
// UpdateL2CrossMsgHash update layer2 cross message hash
func (c *CrossMsg) UpdateL2CrossMsgHash(ctx context.Context, l2Hash, msgHash common.Hash, dbTx ...*gorm.DB) error {
db := c.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&CrossMsg{}).
Where("layer2_hash = ?", l2Hash.String()).
Update("msg_hash", msgHash.String()).
Error
if err != nil {
return fmt.Errorf("CrossMsg.UpdateL2CrossMsgHash error: %w", err)
}
return nil
}
// UpdateL2BlockTimestamp update layer2 cross message block timestamp
func (c *CrossMsg) UpdateL2BlockTimestamp(ctx context.Context, height uint64, timestamp time.Time) error {
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("height = ? AND msg_type = ?", height, Layer2Msg).
Update("block_timestamp", timestamp).Error
if err != nil {
return fmt.Errorf("CrossMsg.UpdateL2BlockTimestamp error: %w", err)
}
return nil
}
// DeleteL2CrossMsgFromHeight delete layer2 cross messages from given height
func (c *CrossMsg) DeleteL2CrossMsgFromHeight(ctx context.Context, height uint64, dbTx ...*gorm.DB) error {
db := c.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&CrossMsg{}).Delete("height > ? AND msg_type = ?", height, Layer2Msg).Error
if err != nil {
return fmt.Errorf("CrossMsg.DeleteL2CrossMsgFromHeight error: %w", err)
}
return nil
}
// General Operations
// GetTotalCrossMsgCountByAddress get total cross msg count by address
func (c *CrossMsg) GetTotalCrossMsgCountByAddress(ctx context.Context, sender string) (uint64, error) {
var count int64
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("sender = ?", sender).
Count(&count).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("CrossMsg.GetTotalCrossMsgCountByAddress error: %w", err)
}
return uint64(count), nil
}
// GetCrossMsgsByAddressWithOffset get cross msgs by address with offset
func (c *CrossMsg) GetCrossMsgsByAddressWithOffset(ctx context.Context, sender string, offset int, limit int) ([]CrossMsg, error) {
var messages []CrossMsg
err := c.db.WithContext(ctx).Model(&CrossMsg{}).
Where("sender = ?", sender).
Order("block_timestamp DESC NULLS FIRST, id DESC").
Limit(limit).
Offset(offset).
Find(&messages).
Error
if err != nil {
return nil, fmt.Errorf("CrossMsg.GetCrossMsgsByAddressWithOffset error: %w", err)
}
return messages, nil
}

View File

@@ -0,0 +1,215 @@
package orm
import (
"context"
"fmt"
"time"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
)
// L2SentMsg defines the struct for l2_sent_msg table record
type L2SentMsg struct {
db *gorm.DB `gorm:"column:-"`
ID uint64 `json:"id" gorm:"column:id"`
OriginalSender string `json:"original_sender" gorm:"column:original_sender;default:''"`
TxHash string `json:"tx_hash" gorm:"column:tx_hash"`
MsgHash string `json:"msg_hash" gorm:"column:msg_hash"`
Sender string `json:"sender" gorm:"column:sender"`
Target string `json:"target" gorm:"column:target"`
Value string `json:"value" gorm:"column:value"`
Height uint64 `json:"height" gorm:"column:height"`
Nonce uint64 `json:"nonce" gorm:"column:nonce"`
BatchIndex uint64 `json:"batch_index" gorm:"column:batch_index;default:0"`
MsgProof string `json:"msg_proof" gorm:"column:msg_proof;default:''"`
MsgData string `json:"msg_data" gorm:"column:msg_data;default:''"`
CreatedAt *time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt *time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"column:deleted_at;default:NULL"`
}
// NewL2SentMsg create an NewL2SentMsg instance
func NewL2SentMsg(db *gorm.DB) *L2SentMsg {
return &L2SentMsg{db: db}
}
// TableName returns the table name for the L2SentMsg model.
func (*L2SentMsg) TableName() string {
return "l2_sent_msg"
}
// GetL2SentMsgByHash get l2 sent msg by hash
func (l *L2SentMsg) GetL2SentMsgByHash(ctx context.Context, msgHash string) (*L2SentMsg, error) {
var result L2SentMsg
err := l.db.WithContext(ctx).Model(&L2SentMsg{}).
Where("msg_hash = ?", msgHash).
First(&result).
Error
if err != nil {
return nil, fmt.Errorf("L2SentMsg.GetL2SentMsgByHash error: %w", err)
}
return &result, nil
}
// GetLatestSentMsgHeightOnL2 get latest sent msg height on l2
func (l *L2SentMsg) GetLatestSentMsgHeightOnL2(ctx context.Context) (uint64, error) {
var result L2SentMsg
err := l.db.WithContext(ctx).Model(&L2SentMsg{}).
Select("height").
Order("nonce DESC").
First(&result).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("L2SentMsg.GetLatestSentMsgHeightOnL2 error: %w", err)
}
return result.Height, nil
}
// GetClaimableL2SentMsgByAddressWithOffset get claimable l2 sent msg by address with offset
func (l *L2SentMsg) GetClaimableL2SentMsgByAddressWithOffset(ctx context.Context, address string, offset int, limit int) ([]*L2SentMsg, error) {
var results []*L2SentMsg
err := l.db.WithContext(ctx).Raw(`SELECT * FROM l2_sent_msg WHERE id NOT IN (SELECT l2_sent_msg.id FROM l2_sent_msg INNER JOIN relayed_msg ON l2_sent_msg.msg_hash = relayed_msg.msg_hash WHERE l2_sent_msg.deleted_at IS NULL AND relayed_msg.deleted_at IS NULL) AND (original_sender=$1 OR sender = $1) AND msg_proof !='' ORDER BY id DESC LIMIT $2 OFFSET $3;`, address, limit, offset).
Scan(&results).Error
if err != nil {
return nil, fmt.Errorf("L2SentMsg.GetClaimableL2SentMsgByAddressWithOffset error: %w", err)
}
return results, nil
}
// GetClaimableL2SentMsgByAddressTotalNum get claimable l2 sent msg by address total num
func (l *L2SentMsg) GetClaimableL2SentMsgByAddressTotalNum(ctx context.Context, address string) (uint64, error) {
var count uint64
err := l.db.WithContext(ctx).Raw(`SELECT COUNT(*) FROM l2_sent_msg WHERE id NOT IN (SELECT l2_sent_msg.id FROM l2_sent_msg INNER JOIN relayed_msg ON l2_sent_msg.msg_hash = relayed_msg.msg_hash WHERE l2_sent_msg.deleted_at IS NULL AND relayed_msg.deleted_at IS NULL) AND (original_sender=$1 OR sender = $1) AND msg_proof !='';`, address).
Scan(&count).Error
if err != nil {
return 0, fmt.Errorf("L2SentMsg.GetClaimableL2SentMsgByAddressTotalNum error: %w", err)
}
return count, nil
}
// GetLatestL2SentMsgBatchIndex get latest l2 sent msg batch index
func (l *L2SentMsg) GetLatestL2SentMsgBatchIndex(ctx context.Context) (int64, error) {
var result L2SentMsg
err := l.db.WithContext(ctx).Model(&L2SentMsg{}).
Where("batch_index != 0").
Order("batch_index DESC").
Select("batch_index").
First(&result).
Error
if err != nil {
return -1, fmt.Errorf("L2SentMsg.GetLatestL2SentMsgBatchIndex error: %w", err)
}
// Watch for overflow, tho its not likely to happen
return int64(result.Height), nil
}
// GetL2SentMsgMsgHashByHeightRange get l2 sent msg msg hash by height range
func (l *L2SentMsg) GetL2SentMsgMsgHashByHeightRange(ctx context.Context, startHeight, endHeight uint64) ([]*L2SentMsg, error) {
var results []*L2SentMsg
err := l.db.WithContext(ctx).Model(&L2SentMsg{}).
Where("height >= ? AND height <= ?", startHeight, endHeight).
Order("nonce ASC").
Find(&results).
Error
if err != nil {
return nil, fmt.Errorf("L2SentMsg.GetL2SentMsgMsgHashByHeightRange error: %w", err)
}
return results, nil
}
// GetL2SentMessageByNonce get l2 sent message by nonce
func (l *L2SentMsg) GetL2SentMessageByNonce(ctx context.Context, nonce uint64) (*L2SentMsg, error) {
var result L2SentMsg
err := l.db.WithContext(ctx).Model(&L2SentMsg{}).
Where("nonce = ?", nonce).
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, fmt.Errorf("L2SentMsg.GetL2SentMessageByNonce error: %w", err)
}
return &result, nil
}
// GetLatestL2SentMsgLEHeight get latest l2 sent msg less than or equal to end block number
func (l *L2SentMsg) GetLatestL2SentMsgLEHeight(ctx context.Context, endBlockNumber uint64) (*L2SentMsg, error) {
var result L2SentMsg
err := l.db.WithContext(ctx).Model(&L2SentMsg{}).
Where("height <= ?", endBlockNumber).
Order("nonce DESC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, fmt.Errorf("L2SentMsg.GetLatestL2SentMsgLEHeight error: %w", err)
}
return &result, nil
}
// InsertL2SentMsg batch insert l2 sent msg
func (l *L2SentMsg) InsertL2SentMsg(ctx context.Context, messages []*L2SentMsg, dbTx ...*gorm.DB) error {
if len(messages) == 0 {
return nil
}
db := l.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&L2SentMsg{}).Create(&messages).Error
if err != nil {
l2hashes := make([]string, 0, len(messages))
heights := make([]uint64, 0, len(messages))
for _, msg := range messages {
l2hashes = append(l2hashes, msg.TxHash)
heights = append(heights, msg.Height)
}
log.Error("failed to insert l2 sent messages", "l2hashes", l2hashes, "heights", heights, "err", err)
return fmt.Errorf("L2SentMsg.InsertL2SentMsg error: %w", err)
}
return nil
}
// UpdateL2MessageProof update l2 message proof in db tx
func (l *L2SentMsg) UpdateL2MessageProof(ctx context.Context, msgHash string, proof string, batchIndex uint64, dbTx ...*gorm.DB) error {
db := l.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&L2SentMsg{}).
Where("msg_hash = ?", msgHash).
Updates(map[string]interface{}{
"msg_proof": proof,
"batch_index": batchIndex,
}).Error
if err != nil {
return fmt.Errorf("L2SentMsg.UpdateL2MessageProof error: %w", err)
}
return nil
}
// DeleteL2SentMsgAfterHeight delete l2 sent msg after height
func (l *L2SentMsg) DeleteL2SentMsgAfterHeight(ctx context.Context, height uint64, dbTx ...*gorm.DB) error {
db := l.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
err := db.WithContext(ctx).Model(&L2SentMsg{}).Delete("height > ?", height).Error
if err != nil {
return fmt.Errorf("L2SentMsg.DeleteL2SentMsgAfterHeight error: %w", err)
}
return nil
}

View File

@@ -0,0 +1,142 @@
package orm
import (
"context"
"fmt"
"time"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
)
// RelayedMsg is the struct for relayed_msg table
type RelayedMsg struct {
db *gorm.DB `gorm:"column:-"`
ID uint64 `json:"id" gorm:"column:id"`
MsgHash string `json:"msg_hash" gorm:"column:msg_hash"`
Height uint64 `json:"height" gorm:"column:height"`
Layer1Hash string `json:"layer1_hash" gorm:"column:layer1_hash;default:''"`
Layer2Hash string `json:"layer2_hash" gorm:"column:layer2_hash;default:''"`
CreatedAt *time.Time `json:"created_at" gorm:"column:created_at"`
UpdatedAt *time.Time `json:"updated_at" gorm:"column:updated_at"`
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"column:deleted_at;default:NULL"`
}
// NewRelayedMsg create an NewRelayedMsg instance
func NewRelayedMsg(db *gorm.DB) *RelayedMsg {
return &RelayedMsg{db: db}
}
// TableName returns the table name for the RelayedMsg model.
func (*RelayedMsg) TableName() string {
return "relayed_msg"
}
// GetRelayedMsgByHash get relayed msg by hash
func (r *RelayedMsg) GetRelayedMsgByHash(ctx context.Context, msgHash string) (*RelayedMsg, error) {
var result RelayedMsg
err := r.db.WithContext(ctx).Model(&RelayedMsg{}).
Where("msg_hash = ?", msgHash).
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, fmt.Errorf("RelayedMsg.GetRelayedMsgByHash error: %w", err)
}
return &result, nil
}
// GetLatestRelayedHeightOnL1 get latest relayed height on l1
func (r *RelayedMsg) GetLatestRelayedHeightOnL1(ctx context.Context) (uint64, error) {
var result RelayedMsg
err := r.db.WithContext(ctx).Model(&RelayedMsg{}).
Select("height").
Where("layer1_hash != ''").
Order("height DESC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("RelayedMsg.GetLatestRelayedHeightOnL1 error: %w", err)
}
return result.Height, err
}
// GetLatestRelayedHeightOnL2 get latest relayed height on l2
func (r *RelayedMsg) GetLatestRelayedHeightOnL2(ctx context.Context) (uint64, error) {
var result RelayedMsg
err := r.db.WithContext(ctx).Model(&RelayedMsg{}).
Select("height").
Where("layer2_hash != ''").
Order("height DESC").
First(&result).
Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return 0, nil
}
return 0, fmt.Errorf("RelayedMsg.GetLatestRelayedHeightOnL2 error: %w", err)
}
return result.Height, nil
}
// InsertRelayedMsg batch insert relayed msg into db and return the transaction
func (r *RelayedMsg) InsertRelayedMsg(ctx context.Context, messages []*RelayedMsg, dbTx ...*gorm.DB) error {
if len(messages) == 0 {
return nil
}
db := r.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&RelayedMsg{}).Create(&messages).Error
if err != nil {
l2hashes := make([]string, 0, len(messages))
l1hashes := make([]string, 0, len(messages))
heights := make([]uint64, 0, len(messages))
for _, msg := range messages {
l2hashes = append(l2hashes, msg.Layer2Hash)
l1hashes = append(l1hashes, msg.Layer1Hash)
heights = append(heights, msg.Height)
}
log.Error("failed to insert l2 sent messages", "l2hashes", l2hashes, "l1hashes", l1hashes, "heights", heights, "err", err)
return fmt.Errorf("RelayedMsg.InsertRelayedMsg error: %w", err)
}
return nil
}
// DeleteL1RelayedHashAfterHeight delete l1 relayed hash after height
func (r *RelayedMsg) DeleteL1RelayedHashAfterHeight(ctx context.Context, height uint64, dbTx ...*gorm.DB) error {
db := r.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&RelayedMsg{}).
Delete("height > ? AND layer1_hash != ''", height).Error
if err != nil {
return fmt.Errorf("RelayedMsg.DeleteL1RelayedHashAfterHeight error: %w", err)
}
return nil
}
// DeleteL2RelayedHashAfterHeight delete l2 relayed hash after heights
func (r *RelayedMsg) DeleteL2RelayedHashAfterHeight(ctx context.Context, height uint64, dbTx ...*gorm.DB) error {
db := r.db
if len(dbTx) > 0 && dbTx[0] != nil {
db = dbTx[0]
}
db.WithContext(ctx)
err := db.Model(&RelayedMsg{}).
Delete("height > ? AND layer2_hash != ''", height).Error
if err != nil {
return fmt.Errorf("RelayedMsg.DeleteL2RelayedHashAfterHeight error: %w", err)
}
return nil
}

View File

@@ -1,14 +1,15 @@
package service
import (
"context"
"strconv"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"gorm.io/gorm"
"bridge-history-api/db"
"bridge-history-api/db/orm"
"bridge-history-api/orm"
)
// Finalized the schema of tx finalized infos
@@ -48,30 +49,33 @@ type TxHistoryInfo struct {
// HistoryService example service.
type HistoryService interface {
GetTxsByAddress(address common.Address, offset int64, limit int64) ([]*TxHistoryInfo, uint64, error)
GetTxsByAddress(address common.Address, offset int, limit int) ([]*TxHistoryInfo, uint64, error)
GetTxsByHashes(hashes []string) ([]*TxHistoryInfo, error)
GetClaimableTxsByAddress(address common.Address, offset int64, limit int64) ([]*TxHistoryInfo, uint64, error)
GetClaimableTxsByAddress(address common.Address, offset int, limit int) ([]*TxHistoryInfo, uint64, error)
}
// NewHistoryService returns a service backed with a "db"
func NewHistoryService(db db.OrmFactory) HistoryService {
service := &historyBackend{db: db, prefix: "Scroll-Bridge-History-Server"}
func NewHistoryService(ctx context.Context, db *gorm.DB) HistoryService {
service := &historyBackend{ctx: ctx, db: db, prefix: "Scroll-Bridge-History-Server"}
return service
}
type historyBackend struct {
prefix string
db db.OrmFactory
ctx context.Context
db *gorm.DB
}
// GetCrossTxClaimInfo get UserClaimInfos by address
func GetCrossTxClaimInfo(msgHash string, db db.OrmFactory) *UserClaimInfo {
l2sentMsg, err := db.GetL2SentMsgByHash(msgHash)
if err != nil {
func GetCrossTxClaimInfo(ctx context.Context, msgHash string, db *gorm.DB) *UserClaimInfo {
l2SentMsgOrm := orm.NewL2SentMsg(db)
rollupOrm := orm.NewRollupBatch(db)
l2sentMsg, err := l2SentMsgOrm.GetL2SentMsgByHash(ctx, msgHash)
if err != nil || l2sentMsg == nil {
log.Debug("GetCrossTxClaimInfo failed", "error", err)
return &UserClaimInfo{}
}
batch, err := db.GetRollupBatchByIndex(l2sentMsg.BatchIndex)
batch, err := rollupOrm.GetRollupBatchByIndex(ctx, l2sentMsg.BatchIndex)
if err != nil {
log.Debug("GetCrossTxClaimInfo failed", "error", err)
return &UserClaimInfo{}
@@ -89,10 +93,11 @@ func GetCrossTxClaimInfo(msgHash string, db db.OrmFactory) *UserClaimInfo {
}
func updateCrossTxHash(msgHash string, txInfo *TxHistoryInfo, db db.OrmFactory) {
relayed, err := db.GetRelayedMsgByHash(msgHash)
func updateCrossTxHash(ctx context.Context, msgHash string, txInfo *TxHistoryInfo, db *gorm.DB) {
relayed := orm.NewRelayedMsg(db)
relayed, err := relayed.GetRelayedMsgByHash(ctx, msgHash)
if err != nil {
log.Error("updateCrossTxHash failed", "error", err)
log.Debug("updateCrossTxHash failed", "error", err)
return
}
if relayed == nil {
@@ -112,13 +117,15 @@ func updateCrossTxHash(msgHash string, txInfo *TxHistoryInfo, db db.OrmFactory)
}
// GetClaimableTxsByAddress get all claimable txs under given address
func (h *historyBackend) GetClaimableTxsByAddress(address common.Address, offset int64, limit int64) ([]*TxHistoryInfo, uint64, error) {
func (h *historyBackend) GetClaimableTxsByAddress(address common.Address, offset int, limit int) ([]*TxHistoryInfo, uint64, error) {
var txHistories []*TxHistoryInfo
total, err := h.db.GetClaimableL2SentMsgByAddressTotalNum(address.Hex())
l2SentMsgOrm := orm.NewL2SentMsg(h.db)
l2CrossMsgOrm := orm.NewCrossMsg(h.db)
total, err := l2SentMsgOrm.GetClaimableL2SentMsgByAddressTotalNum(h.ctx, address.Hex())
if err != nil || total == 0 {
return txHistories, 0, err
}
results, err := h.db.GetClaimableL2SentMsgByAddressWithOffset(address.Hex(), offset, limit)
results, err := l2SentMsgOrm.GetClaimableL2SentMsgByAddressWithOffset(h.ctx, address.Hex(), offset, limit)
if err != nil || len(results) == 0 {
return txHistories, 0, err
}
@@ -126,7 +133,7 @@ func (h *historyBackend) GetClaimableTxsByAddress(address common.Address, offset
for _, result := range results {
msgHashList = append(msgHashList, result.MsgHash)
}
crossMsgs, err := h.db.GetL2CrossMsgByMsgHashList(msgHashList)
crossMsgs, err := l2CrossMsgOrm.GetL2CrossMsgByMsgHashList(h.ctx, msgHashList)
// crossMsgs can be empty, because they can be emitted by user directly call contract
if err != nil {
return txHistories, 0, err
@@ -141,7 +148,7 @@ func (h *historyBackend) GetClaimableTxsByAddress(address common.Address, offset
IsL1: false,
BlockNumber: result.Height,
FinalizeTx: &Finalized{},
ClaimInfo: GetCrossTxClaimInfo(result.MsgHash, h.db),
ClaimInfo: GetCrossTxClaimInfo(h.ctx, result.MsgHash, h.db),
}
if crossMsg, exist := crossMsgMap[result.MsgHash]; exist {
txInfo.Amount = crossMsg.Amount
@@ -155,13 +162,14 @@ func (h *historyBackend) GetClaimableTxsByAddress(address common.Address, offset
}
// GetTxsByAddress get all txs under given address
func (h *historyBackend) GetTxsByAddress(address common.Address, offset int64, limit int64) ([]*TxHistoryInfo, uint64, error) {
func (h *historyBackend) GetTxsByAddress(address common.Address, offset int, limit int) ([]*TxHistoryInfo, uint64, error) {
var txHistories []*TxHistoryInfo
total, err := h.db.GetTotalCrossMsgCountByAddress(address.String())
utilOrm := orm.NewCrossMsg(h.db)
total, err := utilOrm.GetTotalCrossMsgCountByAddress(h.ctx, address.String())
if err != nil || total == 0 {
return txHistories, 0, err
}
result, err := h.db.GetCrossMsgsByAddressWithOffset(address.String(), offset, limit)
result, err := utilOrm.GetCrossMsgsByAddressWithOffset(h.ctx, address.String(), offset, limit)
if err != nil {
return nil, 0, err
@@ -178,9 +186,9 @@ func (h *historyBackend) GetTxsByAddress(address common.Address, offset int64, l
FinalizeTx: &Finalized{
Hash: "",
},
ClaimInfo: GetCrossTxClaimInfo(msg.MsgHash, h.db),
ClaimInfo: GetCrossTxClaimInfo(h.ctx, msg.MsgHash, h.db),
}
updateCrossTxHash(msg.MsgHash, txHistory, h.db)
updateCrossTxHash(h.ctx, msg.MsgHash, txHistory, h.db)
txHistories = append(txHistories, txHistory)
}
return txHistories, total, nil
@@ -189,8 +197,9 @@ func (h *historyBackend) GetTxsByAddress(address common.Address, offset int64, l
// GetTxsByHashes get tx infos under given tx hashes
func (h *historyBackend) GetTxsByHashes(hashes []string) ([]*TxHistoryInfo, error) {
txHistories := make([]*TxHistoryInfo, 0)
CrossMsgOrm := orm.NewCrossMsg(h.db)
for _, hash := range hashes {
l1result, err := h.db.GetL1CrossMsgByHash(common.HexToHash(hash))
l1result, err := CrossMsgOrm.GetL1CrossMsgByHash(h.ctx, common.HexToHash(hash))
if err != nil {
return nil, err
}
@@ -207,11 +216,11 @@ func (h *historyBackend) GetTxsByHashes(hashes []string) ([]*TxHistoryInfo, erro
Hash: "",
},
}
updateCrossTxHash(l1result.MsgHash, txHistory, h.db)
updateCrossTxHash(h.ctx, l1result.MsgHash, txHistory, h.db)
txHistories = append(txHistories, txHistory)
continue
}
l2result, err := h.db.GetL2CrossMsgByHash(common.HexToHash(hash))
l2result, err := CrossMsgOrm.GetL2CrossMsgByHash(h.ctx, common.HexToHash(hash))
if err != nil {
return nil, err
}
@@ -227,9 +236,9 @@ func (h *historyBackend) GetTxsByHashes(hashes []string) ([]*TxHistoryInfo, erro
FinalizeTx: &Finalized{
Hash: "",
},
ClaimInfo: GetCrossTxClaimInfo(l2result.MsgHash, h.db),
ClaimInfo: GetCrossTxClaimInfo(h.ctx, l2result.MsgHash, h.db),
}
updateCrossTxHash(l2result.MsgHash, txHistory, h.db)
updateCrossTxHash(h.ctx, l2result.MsgHash, txHistory, h.db)
txHistories = append(txHistories, txHistory)
continue
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/ethereum/go-ethereum/log"
backendabi "bridge-history-api/abi"
"bridge-history-api/db/orm"
"bridge-history-api/orm"
)
// CachedParsedTxCalldata store parsed batch infos
@@ -46,6 +46,7 @@ func ParseBackendL1EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Amount: event.Amount.String(),
Asset: int(orm.ETH),
Layer1Hash: vlog.TxHash.Hex(),
MsgType: int(orm.Layer1Msg),
MsgHash: msgHash,
})
case backendabi.L1DepositERC20Sig:
@@ -64,6 +65,7 @@ func ParseBackendL1EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer1Hash: vlog.TxHash.Hex(),
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
MsgType: int(orm.Layer1Msg),
MsgHash: msgHash,
})
case backendabi.L1DepositERC721Sig:
@@ -82,6 +84,7 @@ func ParseBackendL1EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
TokenIDs: event.TokenID.String(),
MsgType: int(orm.Layer1Msg),
MsgHash: msgHash,
})
case backendabi.L1DepositERC1155Sig:
@@ -101,6 +104,7 @@ func ParseBackendL1EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer2Token: event.L2Token.Hex(),
TokenIDs: event.TokenID.String(),
Amount: event.Amount.String(),
MsgType: int(orm.Layer1Msg),
MsgHash: msgHash,
})
case backendabi.L1SentMessageEventSignature:
@@ -128,6 +132,7 @@ func ParseBackendL1EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
TokenIDs: convertBigIntArrayToString(event.TokenIDs),
MsgType: int(orm.Layer1Msg),
MsgHash: msgHash,
})
case backendabi.L1BatchDepositERC1155Sig:
@@ -147,6 +152,7 @@ func ParseBackendL1EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer2Token: event.L2Token.Hex(),
TokenIDs: convertBigIntArrayToString(event.TokenIDs),
TokenAmounts: convertBigIntArrayToString(event.TokenAmounts),
MsgType: int(orm.Layer1Msg),
MsgHash: msgHash,
})
case backendabi.L1RelayedMessageEventSignature:
@@ -194,6 +200,7 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Amount: event.Amount.String(),
Asset: int(orm.ETH),
Layer2Hash: vlog.TxHash.Hex(),
MsgType: int(orm.Layer2Msg),
MsgHash: l2SentMsgs[len(l2SentMsgs)-1].MsgHash,
})
case backendabi.L2WithdrawERC20Sig:
@@ -213,6 +220,7 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer2Hash: vlog.TxHash.Hex(),
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
MsgType: int(orm.Layer2Msg),
MsgHash: l2SentMsgs[len(l2SentMsgs)-1].MsgHash,
})
case backendabi.L2WithdrawERC721Sig:
@@ -232,6 +240,7 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
TokenIDs: event.TokenID.String(),
MsgType: int(orm.Layer2Msg),
MsgHash: l2SentMsgs[len(l2SentMsgs)-1].MsgHash,
})
case backendabi.L2WithdrawERC1155Sig:
@@ -252,6 +261,7 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer2Token: event.L2Token.Hex(),
TokenIDs: event.TokenID.String(),
Amount: event.Amount.String(),
MsgType: int(orm.Layer2Msg),
MsgHash: l2SentMsgs[len(l2SentMsgs)-1].MsgHash,
})
case backendabi.L2BatchWithdrawERC721Sig:
@@ -270,6 +280,7 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer1Hash: vlog.TxHash.Hex(),
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
MsgType: int(orm.Layer2Msg),
TokenIDs: convertBigIntArrayToString(event.TokenIDs),
MsgHash: l2SentMsgs[len(l2SentMsgs)-1].MsgHash,
})
@@ -289,6 +300,7 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
Layer1Hash: vlog.TxHash.Hex(),
Layer1Token: event.L1Token.Hex(),
Layer2Token: event.L2Token.Hex(),
MsgType: int(orm.Layer2Msg),
TokenIDs: convertBigIntArrayToString(event.TokenIDs),
TokenAmounts: convertBigIntArrayToString(event.TokenAmounts),
MsgHash: l2SentMsgs[len(l2SentMsgs)-1].MsgHash,
@@ -334,7 +346,6 @@ func ParseBackendL2EventLogs(logs []types.Log) ([]*orm.CrossMsg, []*orm.RelayedM
// ParseBatchInfoFromScrollChain parses ScrollChain events
func ParseBatchInfoFromScrollChain(ctx context.Context, client *ethclient.Client, logs []types.Log) ([]*orm.RollupBatch, error) {
var rollupBatches []*orm.RollupBatch
cache := make(map[string]CachedParsedTxCalldata)
for _, vlog := range logs {
switch vlog.Topics[0] {
case backendabi.L1CommitBatchEventSignature:
@@ -344,42 +355,22 @@ func ParseBatchInfoFromScrollChain(ctx context.Context, client *ethclient.Client
log.Warn("Failed to unpack CommitBatch event", "err", err)
return rollupBatches, err
}
if _, ok := cache[vlog.TxHash.Hex()]; ok {
c := cache[vlog.TxHash.Hex()]
c.CallDataIndex++
rollupBatches = append(rollupBatches, &orm.RollupBatch{
CommitHeight: vlog.BlockNumber,
BatchIndex: c.BatchIndices[c.CallDataIndex],
BatchHash: event.BatchHash.Hex(),
StartBlockNumber: c.StartBlocks[c.CallDataIndex],
EndBlockNumber: c.EndBlocks[c.CallDataIndex],
})
cache[vlog.TxHash.Hex()] = c
continue
}
commitTx, isPending, err := client.TransactionByHash(ctx, vlog.TxHash)
if err != nil || isPending {
log.Warn("Failed to get commit Batch tx receipt or the tx is still pending", "err", err)
return rollupBatches, err
}
indices, startBlocks, endBlocks, err := GetBatchRangeFromCalldataV1(commitTx.Data())
index, startBlock, endBlock, err := GetBatchRangeFromCalldataV2(commitTx.Data())
if err != nil {
log.Warn("Failed to get batch range from calldata", "hash", commitTx.Hash().Hex(), "height", vlog.BlockNumber)
return rollupBatches, err
}
cache[vlog.TxHash.Hex()] = CachedParsedTxCalldata{
CallDataIndex: 0,
BatchIndices: indices,
StartBlocks: startBlocks,
EndBlocks: endBlocks,
}
rollupBatches = append(rollupBatches, &orm.RollupBatch{
CommitHeight: vlog.BlockNumber,
BatchIndex: indices[0],
BatchIndex: index,
BatchHash: event.BatchHash.Hex(),
StartBlockNumber: startBlocks[0],
EndBlockNumber: endBlocks[0],
StartBlockNumber: startBlock,
EndBlockNumber: endBlock,
})
default:

View File

@@ -8,10 +8,10 @@ require (
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/scroll-tech/go-ethereum v1.10.14-0.20230613025759-f055f50f9d56
github.com/smartystreets/goconvey v1.8.0
github.com/stretchr/testify v1.8.2
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
golang.org/x/sync v0.1.0
gorm.io/gorm v1.25.1
github.com/stretchr/testify v1.8.3
github.com/urfave/cli/v2 v2.25.7
golang.org/x/sync v0.3.0
gorm.io/gorm v1.25.2
)
require (
@@ -35,7 +35,7 @@ require (
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -52,8 +52,8 @@ require (
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/time v0.3.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect

View File

@@ -18,7 +18,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
@@ -74,8 +73,8 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -119,13 +118,8 @@ github.com/smartystreets/goconvey v1.8.0 h1:Oi49ha/2MURE0WexF052Z0m+BNSGirfjg5RL
github.com/smartystreets/goconvey v1.8.0/go.mod h1:EdX8jtrTIj26jmjCOVNMVSIYAtgexqXKHOXW2Dx9JLg=
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
@@ -133,8 +127,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
@@ -142,15 +136,15 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -158,10 +152,10 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -174,8 +168,7 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64=
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=

View File

@@ -52,7 +52,7 @@ type Layer1Relayer struct {
gasPriceDiff uint64
l1MessageOrm *orm.L1Message
l1Block *orm.L1Block
l1BlockOrm *orm.L1Block
}
// NewLayer1Relayer will return a new instance of Layer1RelayerClient
@@ -90,7 +90,7 @@ func NewLayer1Relayer(ctx context.Context, db *gorm.DB, cfg *config.RelayerConfi
l1Relayer := &Layer1Relayer{
ctx: ctx,
l1MessageOrm: orm.NewL1Message(db),
l1Block: orm.NewL1Block(db),
l1BlockOrm: orm.NewL1Block(db),
messageSender: messageSender,
l2MessengerABI: bridgeAbi.L2ScrollMessengerABI,
@@ -159,13 +159,13 @@ func (r *Layer1Relayer) processSavedEvent(msg *orm.L1Message) error {
// ProcessGasPriceOracle imports gas price to layer2
func (r *Layer1Relayer) ProcessGasPriceOracle() {
latestBlockHeight, err := r.l1Block.GetLatestL1BlockHeight(r.ctx)
latestBlockHeight, err := r.l1BlockOrm.GetLatestL1BlockHeight(r.ctx)
if err != nil {
log.Warn("Failed to fetch latest L1 block height from db", "err", err)
return
}
blocks, err := r.l1Block.GetL1Blocks(r.ctx, map[string]interface{}{
blocks, err := r.l1BlockOrm.GetL1Blocks(r.ctx, map[string]interface{}{
"number": latestBlockHeight,
})
if err != nil {
@@ -197,7 +197,7 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
return
}
err = r.l1Block.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, hash.String())
err = r.l1BlockOrm.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, hash.String())
if err != nil {
log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
return
@@ -232,14 +232,14 @@ func (r *Layer1Relayer) handleConfirmLoop(ctx context.Context) {
case cfm := <-r.gasOracleSender.ConfirmChan():
if !cfm.IsSuccessful {
// @discuss: maybe make it pending again?
err := r.l1Block.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleFailed, cfm.TxHash.String())
err := r.l1BlockOrm.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleFailed, cfm.TxHash.String())
if err != nil {
log.Warn("UpdateL1GasOracleStatusAndOracleTxHash failed", "err", err)
}
log.Warn("transaction confirmed but failed in layer2", "confirmation", cfm)
} else {
// @todo handle db error
err := r.l1Block.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleImported, cfm.TxHash.String())
err := r.l1BlockOrm.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleImported, cfm.TxHash.String())
if err != nil {
log.Warn("UpdateGasOracleStatusAndOracleTxHash failed", "err", err)
}

View File

@@ -128,8 +128,8 @@ func testL1RelayerGasOracleConfirm(t *testing.T) {
l1BlockOrm := orm.NewL1Block(db)
l1Block := []orm.L1Block{
{Hash: "gas-oracle-1", Number: 0, GasOracleStatus: int16(types.GasOraclePending), BlockStatus: int16(types.L1BlockPending)},
{Hash: "gas-oracle-2", Number: 1, GasOracleStatus: int16(types.GasOraclePending), BlockStatus: int16(types.L1BlockPending)},
{Hash: "gas-oracle-1", Number: 0, GasOracleStatus: int16(types.GasOraclePending)},
{Hash: "gas-oracle-2", Number: 1, GasOracleStatus: int16(types.GasOraclePending)},
}
// Insert test data.
assert.NoError(t, l1BlockOrm.InsertL1Blocks(context.Background(), l1Block))

View File

@@ -171,9 +171,9 @@ func (r *Layer2Relayer) initializeGenesis() error {
chunk := &types.Chunk{
Blocks: []*types.WrappedBlock{{
Header: genesis,
Transactions: nil,
WithdrawTrieRoot: common.Hash{},
Header: genesis,
Transactions: nil,
WithdrawRoot: common.Hash{},
}},
}
@@ -495,9 +495,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() {
r.processingFinalization.Store(txID, hash)
default:
log.Error("encounter unreachable case in ProcessCommittedBatches",
"block_status", status,
)
log.Error("encounter unreachable case in ProcessCommittedBatches", "proving status", status)
}
}

View File

@@ -19,9 +19,9 @@ type BatchProposer struct {
ctx context.Context
db *gorm.DB
batchOrm *orm.Batch
chunkOrm *orm.Chunk
l2Block *orm.L2Block
batchOrm *orm.Batch
chunkOrm *orm.Chunk
l2BlockOrm *orm.L2Block
maxChunkNumPerBatch uint64
maxL1CommitGasPerBatch uint64
@@ -37,7 +37,7 @@ func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, db *
db: db,
batchOrm: orm.NewBatch(db),
chunkOrm: orm.NewChunk(db),
l2Block: orm.NewL2Block(db),
l2BlockOrm: orm.NewL2Block(db),
maxChunkNumPerBatch: cfg.MaxChunkNumPerBatch,
maxL1CommitGasPerBatch: cfg.MaxL1CommitGasPerBatch,
maxL1CommitCalldataSizePerBatch: cfg.MaxL1CommitCalldataSizePerBatch,
@@ -157,7 +157,7 @@ func (p *BatchProposer) proposeBatchChunks() ([]*orm.Chunk, error) {
func (p *BatchProposer) dbChunksToBridgeChunks(dbChunks []*orm.Chunk) ([]*types.Chunk, error) {
chunks := make([]*types.Chunk, len(dbChunks))
for i, c := range dbChunks {
wrappedBlocks, err := p.l2Block.GetL2BlocksInRange(p.ctx, c.StartBlockNumber, c.EndBlockNumber)
wrappedBlocks, err := p.l2BlockOrm.GetL2BlocksInRange(p.ctx, c.StartBlockNumber, c.EndBlockNumber)
if err != nil {
log.Error("Failed to fetch wrapped blocks",
"start number", c.StartBlockNumber, "end number", c.EndBlockNumber, "error", err)

View File

@@ -153,7 +153,6 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error {
Hash: block.Hash().String(),
BaseFee: baseFee,
GasOracleStatus: int16(types.GasOraclePending),
BlockStatus: int16(types.L1BlockPending),
})
}

View File

@@ -169,15 +169,15 @@ func (w *L2WatcherClient) getAndStoreBlockTraces(ctx context.Context, from, to u
log.Info("retrieved block", "height", block.Header().Number, "hash", block.Header().Hash().String())
withdrawTrieRoot, err3 := w.StorageAt(ctx, w.messageQueueAddress, w.withdrawTrieRootSlot, big.NewInt(int64(number)))
withdrawRoot, err3 := w.StorageAt(ctx, w.messageQueueAddress, w.withdrawTrieRootSlot, big.NewInt(int64(number)))
if err3 != nil {
return fmt.Errorf("failed to get withdrawTrieRoot: %v. number: %v", err3, number)
return fmt.Errorf("failed to get withdrawRoot: %v. number: %v", err3, number)
}
blocks = append(blocks, &types.WrappedBlock{
Header: block.Header(),
Transactions: txsToTxsData(block.Transactions()),
WithdrawTrieRoot: common.BytesToHash(withdrawTrieRoot),
Header: block.Header(),
Transactions: txsToTxsData(block.Transactions()),
WithdrawRoot: common.BytesToHash(withdrawRoot),
})
}

View File

@@ -30,6 +30,7 @@ type Batch struct {
EndChunkHash string `json:"end_chunk_hash" gorm:"column:end_chunk_hash"`
StateRoot string `json:"state_root" gorm:"column:state_root"`
WithdrawRoot string `json:"withdraw_root" gorm:"column:withdraw_root"`
ParentBatchHash string `json:"parent_batch_hash" gorm:"column:parent_batch_hash"`
BatchHeader []byte `json:"batch_header" gorm:"column:batch_header"`
// proof
@@ -258,7 +259,8 @@ func (o *Batch) InsertBatch(ctx context.Context, startChunkIndex, endChunkIndex
EndChunkHash: endChunkHash,
EndChunkIndex: endChunkIndex,
StateRoot: chunks[numChunks-1].Blocks[lastChunkBlockNum-1].Header.Root.Hex(),
WithdrawRoot: chunks[numChunks-1].Blocks[lastChunkBlockNum-1].WithdrawTrieRoot.Hex(),
WithdrawRoot: chunks[numChunks-1].Blocks[lastChunkBlockNum-1].WithdrawRoot.Hex(),
ParentBatchHash: parentBatchHash.Hex(),
BatchHeader: batchHeader.Encode(),
ChunkProofsStatus: int16(types.ChunkProofsStatusPending),
ProvingStatus: int16(types.ProvingTaskUnassigned),

View File

@@ -26,6 +26,10 @@ type Chunk struct {
StartBlockTime uint64 `json:"start_block_time" gorm:"column:start_block_time"`
TotalL1MessagesPoppedBefore uint64 `json:"total_l1_messages_popped_before" gorm:"column:total_l1_messages_popped_before"`
TotalL1MessagesPoppedInChunk uint32 `json:"total_l1_messages_popped_in_chunk" gorm:"column:total_l1_messages_popped_in_chunk"`
ParentChunkHash string `json:"parent_chunk_hash" gorm:"column:parent_chunk_hash"`
StateRoot string `json:"state_root" gorm:"column:state_root"`
ParentChunkStateRoot string `json:"parent_chunk_state_root" gorm:"column:parent_chunk_state_root"`
WithdrawRoot string `json:"withdraw_root" gorm:"column:withdraw_root"`
// proof
ProvingStatus int16 `json:"proving_status" gorm:"column:proving_status;default:1"`
@@ -118,6 +122,8 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *types.Chunk, dbTX ...*go
var chunkIndex uint64
var totalL1MessagePoppedBefore uint64
var parentChunkHash string
var parentChunkStateRoot string
parentChunk, err := o.GetLatestChunk(ctx)
if err != nil && !errors.Is(errors.Unwrap(err), gorm.ErrRecordNotFound) {
log.Error("failed to get latest chunk", "err", err)
@@ -130,6 +136,8 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *types.Chunk, dbTX ...*go
if parentChunk != nil {
chunkIndex = parentChunk.Index + 1
totalL1MessagePoppedBefore = parentChunk.TotalL1MessagesPoppedBefore + uint64(parentChunk.TotalL1MessagesPoppedInChunk)
parentChunkHash = parentChunk.Hash
parentChunkStateRoot = parentChunk.StateRoot
}
hash, err := chunk.Hash(totalL1MessagePoppedBefore)
@@ -164,6 +172,10 @@ func (o *Chunk) InsertChunk(ctx context.Context, chunk *types.Chunk, dbTX ...*go
StartBlockTime: chunk.Blocks[0].Header.Time,
TotalL1MessagesPoppedBefore: totalL1MessagePoppedBefore,
TotalL1MessagesPoppedInChunk: uint32(chunk.NumL1Messages(totalL1MessagePoppedBefore)),
ParentChunkHash: parentChunkHash,
StateRoot: chunk.Blocks[numBlocks-1].Header.Root.Hex(),
ParentChunkStateRoot: parentChunkStateRoot,
WithdrawRoot: chunk.Blocks[numBlocks-1].WithdrawRoot.Hex(),
ProvingStatus: int16(types.ProvingTaskUnassigned),
}

View File

@@ -19,10 +19,6 @@ type L1Block struct {
Hash string `json:"hash" gorm:"column:hash"`
BaseFee uint64 `json:"base_fee" gorm:"column:base_fee"`
// import
BlockStatus int16 `json:"block_status" gorm:"column:block_status;default:1"`
ImportTxHash string `json:"import_tx_hash" gorm:"column:import_tx_hash;default:NULL"`
// oracle
GasOracleStatus int16 `json:"oracle_status" gorm:"column:oracle_status;default:1"`
OracleTxHash string `json:"oracle_tx_hash" gorm:"column:oracle_tx_hash;default:NULL"`

View File

@@ -19,15 +19,16 @@ type L2Block struct {
db *gorm.DB `gorm:"column:-"`
// block
Number uint64 `json:"number" gorm:"number"`
Hash string `json:"hash" gorm:"hash"`
ParentHash string `json:"parent_hash" gorm:"parent_hash"`
Header string `json:"header" gorm:"header"`
Transactions string `json:"transactions" gorm:"transactions"`
WithdrawTrieRoot string `json:"withdraw_trie_root" gorm:"withdraw_trie_root"`
TxNum uint32 `json:"tx_num" gorm:"tx_num"`
GasUsed uint64 `json:"gas_used" gorm:"gas_used"`
BlockTimestamp uint64 `json:"block_timestamp" gorm:"block_timestamp"`
Number uint64 `json:"number" gorm:"number"`
Hash string `json:"hash" gorm:"hash"`
ParentHash string `json:"parent_hash" gorm:"parent_hash"`
Header string `json:"header" gorm:"header"`
Transactions string `json:"transactions" gorm:"transactions"`
WithdrawRoot string `json:"withdraw_root" gorm:"withdraw_root"`
StateRoot string `json:"state_root" gorm:"state_root"`
TxNum uint32 `json:"tx_num" gorm:"tx_num"`
GasUsed uint64 `json:"gas_used" gorm:"gas_used"`
BlockTimestamp uint64 `json:"block_timestamp" gorm:"block_timestamp"`
// chunk
ChunkHash string `json:"chunk_hash" gorm:"chunk_hash;default:NULL"`
@@ -67,7 +68,7 @@ func (o *L2Block) GetL2BlocksLatestHeight(ctx context.Context) (uint64, error) {
func (o *L2Block) GetUnchunkedBlocks(ctx context.Context) ([]*types.WrappedBlock, error) {
db := o.db.WithContext(ctx)
db = db.Model(&L2Block{})
db = db.Select("header, transactions, withdraw_trie_root")
db = db.Select("header, transactions, withdraw_root")
db = db.Where("chunk_hash IS NULL")
db = db.Order("number ASC")
@@ -89,7 +90,7 @@ func (o *L2Block) GetUnchunkedBlocks(ctx context.Context) ([]*types.WrappedBlock
return nil, fmt.Errorf("L2Block.GetUnchunkedBlocks error: %w", err)
}
wrappedBlock.WithdrawTrieRoot = common.HexToHash(v.WithdrawTrieRoot)
wrappedBlock.WithdrawRoot = common.HexToHash(v.WithdrawRoot)
wrappedBlocks = append(wrappedBlocks, &wrappedBlock)
}
@@ -133,7 +134,7 @@ func (o *L2Block) GetL2BlocksInRange(ctx context.Context, startBlockNumber uint6
db := o.db.WithContext(ctx)
db = db.Model(&L2Block{})
db = db.Select("header, transactions, withdraw_trie_root")
db = db.Select("header, transactions, withdraw_root")
db = db.Where("number >= ? AND number <= ?", startBlockNumber, endBlockNumber)
db = db.Order("number ASC")
@@ -160,7 +161,7 @@ func (o *L2Block) GetL2BlocksInRange(ctx context.Context, startBlockNumber uint6
return nil, fmt.Errorf("L2Block.GetL2BlocksInRange error: %w, start block: %v, end block: %v", err, startBlockNumber, endBlockNumber)
}
wrappedBlock.WithdrawTrieRoot = common.HexToHash(v.WithdrawTrieRoot)
wrappedBlock.WithdrawRoot = common.HexToHash(v.WithdrawRoot)
wrappedBlocks = append(wrappedBlocks, &wrappedBlock)
}
@@ -184,15 +185,16 @@ func (o *L2Block) InsertL2Blocks(ctx context.Context, blocks []*types.WrappedBlo
}
l2Block := L2Block{
Number: block.Header.Number.Uint64(),
Hash: block.Header.Hash().String(),
ParentHash: block.Header.ParentHash.String(),
Transactions: string(txs),
WithdrawTrieRoot: block.WithdrawTrieRoot.Hex(),
TxNum: uint32(len(block.Transactions)),
GasUsed: block.Header.GasUsed,
BlockTimestamp: block.Header.Time,
Header: string(header),
Number: block.Header.Number.Uint64(),
Hash: block.Header.Hash().String(),
ParentHash: block.Header.ParentHash.String(),
Transactions: string(txs),
WithdrawRoot: block.WithdrawRoot.Hex(),
StateRoot: block.Header.Root.Hex(),
TxNum: uint32(len(block.Transactions)),
GasUsed: block.Header.GasUsed,
BlockTimestamp: block.Header.Time,
Header: string(header),
}
l2Blocks = append(l2Blocks, l2Block)
}

View File

@@ -60,8 +60,8 @@ contract MockBridgeL1 {
/// @notice Emitted when a batch is finalized.
/// @param batchHash The hash of the batch
/// @param stateRoot The state root in layer 2 after this batch.
/// @param withdrawRoot The merkle root in layer2 after this batch.
/// @param stateRoot The state root on layer 2 after this batch.
/// @param withdrawRoot The merkle root on layer2 after this batch.
event FinalizeBatch(bytes32 indexed batchHash, bytes32 stateRoot, bytes32 withdrawRoot);
/***********

View File

@@ -80,8 +80,8 @@ func testImportL2GasPrice(t *testing.T) {
Difficulty: big.NewInt(0),
BaseFee: big.NewInt(0),
},
Transactions: nil,
WithdrawTrieRoot: common.Hash{},
Transactions: nil,
WithdrawRoot: common.Hash{},
},
},
}

View File

@@ -45,9 +45,9 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) {
BaseFee: big.NewInt(0),
}
wrappedBlocks = append(wrappedBlocks, &types.WrappedBlock{
Header: &header,
Transactions: nil,
WithdrawTrieRoot: common.Hash{},
Header: &header,
Transactions: nil,
WithdrawRoot: common.Hash{},
})
}

View File

@@ -75,6 +75,10 @@ linters-settings:
# report about shadowed variables
check-shadowing: true
gosec:
disable:
- G108
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.8
@@ -227,7 +231,12 @@ issues:
- lll
source: "^//go:generate "
text: "long-lines"
# Exclude gosec issues for G108: Profiling endpoint is automatically exposed
- linters:
- gosec
text: "G108"
- linters:
- wsl
text: "return statements should not be cuddled if block has more than two lines"

View File

@@ -24,6 +24,7 @@ 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 ./roller/go.* ./roller/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/
@@ -33,17 +34,17 @@ RUN go mod download -x
# Build coordinator
FROM base as builder
COPY . .
RUN cp -r ./common/libzkp/interface ./coordinator/verifier/lib
COPY --from=zkp-builder /app/target/release/libzkp.so ./coordinator/verifier/lib/
COPY --from=zkp-builder /app/target/release/libzktrie.so ./coordinator/verifier/lib/
RUN cd ./coordinator && go build -v -p 4 -o /bin/coordinator ./cmd && mv verifier/lib /bin/
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 && 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
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/src/coordinator/verifier/lib
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/src/coordinator/internal/logic/verifier/lib
# ENV CHAIN_ID=534353
RUN mkdir -p /src/coordinator/verifier/lib
COPY --from=builder /bin/lib /src/coordinator/verifier/lib
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/

View File

@@ -7,6 +7,7 @@ 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 ./roller/go.* ./roller/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/

View File

@@ -7,6 +7,7 @@ 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 ./roller/go.* ./roller/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/

View File

@@ -7,6 +7,7 @@ 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 ./roller/go.* ./roller/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/

View File

@@ -7,6 +7,7 @@ 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 ./roller/go.* ./roller/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/

View File

@@ -7,6 +7,7 @@ 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 ./roller/go.* ./roller/
COPY ./tests/integration-test/go.* ./tests/integration-test/
COPY ./bridge-history-api/go.* ./bridge-history-api/

View File

@@ -3,7 +3,7 @@ set -uex
profile_name=$1
exclude_dirs=("scroll-tech/bridge/cmd" "scroll-tech/bridge/tests" "scroll-tech/bridge/mock_bridge" "scroll-tech/coordinator/cmd" "scroll-tech/coordinator/verifier")
exclude_dirs=("scroll-tech/bridge/cmd" "scroll-tech/bridge/tests" "scroll-tech/bridge/mock_bridge" "scroll-tech/coordinator/cmd" "scroll-tech/coordinator/internal/logic/verifier")
all_packages=$(go list ./... | grep -v "^scroll-tech/${profile_name}$")
coverpkg="scroll-tech/${profile_name}"

View File

@@ -10,6 +10,8 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/utils"
cutils "scroll-tech/common/utils"
)
type gormLogger struct {
@@ -49,6 +51,14 @@ func InitDB(config *Config) (*gorm.DB, error) {
db, err := gorm.Open(postgres.Open(config.DSN), &gorm.Config{
Logger: &tmpGormLogger,
NowFunc: func() time.Time {
// why set time to UTC.
// if now set this, the inserted data time will use local timezone. like 2023-07-18 18:24:00 CST+8
// but when inserted, store to postgres is 2023-07-18 18:24:00 UTC+0 the timezone is incorrect.
// As mysql dsn user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local, we cant set
// the timezone by loc=Local. but postgres's dsn don't have loc option to set timezone, so just need set the gorm option like that.
return cutils.NowUTC()
},
})
if err != nil {
return nil, err

View File

@@ -7,6 +7,7 @@ import (
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"scroll-tech/common/cmd"
"scroll-tech/common/utils"
@@ -65,8 +66,12 @@ func (i *ImgDB) Stop() error {
if i.id == "" {
i.id = GetContainerID(i.name)
}
timeout := time.Second * 3
if err := cli.ContainerStop(ctx, i.id, &timeout); err != nil {
timeoutSec := 3
timeout := container.StopOptions{
Timeout: &timeoutSec,
}
if err := cli.ContainerStop(ctx, i.id, timeout); err != nil {
return err
}
// remove the stopped container.

View File

@@ -9,6 +9,7 @@ import (
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/scroll-tech/go-ethereum/ethclient"
"scroll-tech/common/cmd"
@@ -135,8 +136,11 @@ func (i *ImgGeth) Stop() error {
// check if container is running, stop the running container.
id := GetContainerID(i.name)
if id != "" {
timeout := time.Second * 3
if err := cli.ContainerStop(ctx, id, &timeout); err != nil {
timeoutSec := 3
timeout := container.StopOptions{
Timeout: &timeoutSec,
}
if err := cli.ContainerStop(ctx, id, timeout); err != nil {
return err
}
i.id = id

View File

@@ -3,22 +3,23 @@ module scroll-tech/common
go 1.19
require (
github.com/docker/docker v20.10.21+incompatible
github.com/docker/docker v23.0.6+incompatible
github.com/jmoiron/sqlx v1.3.5
github.com/lib/pq v1.10.7
github.com/lib/pq v1.10.9
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.18
github.com/mattn/go-isatty v0.0.19
github.com/modern-go/reflect2 v1.0.2
github.com/orcaman/concurrent-map v1.0.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20230613025759-f055f50f9d56
github.com/stretchr/testify v1.8.2
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
github.com/stretchr/testify v1.8.3
github.com/urfave/cli/v2 v2.25.7
gorm.io/driver/postgres v1.5.0
gorm.io/gorm v1.25.1
gorm.io/gorm v1.25.2
)
require (
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -36,7 +37,7 @@ require (
github.com/go-kit/kit v0.9.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
@@ -55,23 +56,23 @@ require (
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.0 // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.14 // indirect
github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.0 // indirect
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.27.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
github.com/opentracing/opentracing-go v1.1.0 // indirect
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
github.com/pkg/errors v0.9.1 // indirect
@@ -84,7 +85,6 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/scroll-tech/zktrie v0.5.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
@@ -92,14 +92,14 @@ require (
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.8.0 // indirect
golang.org/x/tools v0.11.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

View File

@@ -18,13 +18,13 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
@@ -63,7 +63,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -80,8 +79,8 @@ github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMa
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.21+incompatible h1:UTLdBmHk3bEY+w8qeO5KttOhy6OmXWsl/FEet9Uswog=
github.com/docker/docker v20.10.21+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v23.0.6+incompatible h1:aBD4np894vatVX99UTx/GyOUOK4uEcROwA3+bQhEcoU=
github.com/docker/docker v23.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -121,8 +120,8 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
@@ -216,8 +215,9 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.3.0 h1:/NQi8KHMpKWHInxXesC8yD4DhkXPrVhmnwYkjp9AmBA=
github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
@@ -263,8 +263,8 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
@@ -279,16 +279,16 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -296,8 +296,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI=
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
@@ -325,8 +325,8 @@ github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754=
github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
@@ -384,8 +384,6 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -407,8 +405,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
@@ -418,8 +416,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
@@ -449,8 +447,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -480,8 +478,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -506,8 +504,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -522,8 +520,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -562,15 +561,14 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -582,8 +580,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -605,7 +603,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -622,8 +619,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -696,9 +693,8 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64=
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -13,12 +13,12 @@ import (
const nonZeroByteGas uint64 = 16
const zeroByteGas uint64 = 4
// WrappedBlock contains the block's Header, Transactions and WithdrawTrieRoot hash.
// WrappedBlock contains the block's Header, Transactions and WithdrawRoot hash.
type WrappedBlock struct {
Header *types.Header `json:"header"`
// Transactions is only used for recover types.Transactions, the from of types.TransactionData field is missing.
Transactions []*types.TransactionData `json:"transactions"`
WithdrawTrieRoot common.Hash `json:"withdraw_trie_root,omitempty"`
Transactions []*types.TransactionData `json:"transactions"`
WithdrawRoot common.Hash `json:"withdraw_trie_root,omitempty"`
}
// NumL1Messages returns the number of L1 messages in this block.

View File

@@ -5,26 +5,6 @@ import (
"fmt"
)
// L1BlockStatus represents current l1 block processing status
type L1BlockStatus int
const (
// L1BlockUndefined : undefined l1 block status
L1BlockUndefined L1BlockStatus = iota
// L1BlockPending represents the l1 block status is pending
L1BlockPending
// L1BlockImporting represents the l1 block status is importing
L1BlockImporting
// L1BlockImported represents the l1 block status is imported
L1BlockImported
// L1BlockFailed represents the l1 block status is failed
L1BlockFailed
)
// GasOracleStatus represents current gas oracle processing status
type GasOracleStatus int
@@ -115,18 +95,24 @@ func (s RollerProveStatus) String() string {
}
}
// RollerFailureType is the type of a roller session's failure
type RollerFailureType int
// ProverTaskFailureType the type of prover task failure
type ProverTaskFailureType int
const (
// RollerFailureTypeUndefined indicates an unknown roller failure type
RollerFailureTypeUndefined RollerFailureType = iota
// ProverTaskFailureTypeUndefined indicates an unknown roller failure type
ProverTaskFailureTypeUndefined ProverTaskFailureType = iota
// ProverTaskFailureTypeTimeout prover task failure of timeout
ProverTaskFailureTypeTimeout
)
func (s RollerFailureType) String() string {
switch s {
func (r ProverTaskFailureType) String() string {
switch r {
case ProverTaskFailureTypeUndefined:
return "prover task failure undefined"
case ProverTaskFailureTypeTimeout:
return "prover task failure timeout"
default:
return fmt.Sprintf("Undefined (%d)", int32(s))
return "illegal prover task failure type"
}
}

9
common/utils/timezone.go Normal file
View File

@@ -0,0 +1,9 @@
package utils
import "time"
// NowUTC get the utc time.Now
func NowUTC() time.Time {
utc, _ := time.LoadLocation("")
return time.Now().In(utc)
}

View File

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

View File

@@ -4,7 +4,7 @@
> L1ERC1155Gateway
The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT in layer 1 and finalize withdraw the NFTs from layer 2.
The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT on layer 1 and finalize withdraw the NFTs from layer 2.
*The deposited NFTs are held in this gateway. On finalizing withdraw, the corresponding NFT will be transfer to the recipient directly. This will be changed if we have more specific scenarios.*
@@ -24,7 +24,7 @@ Deposit a list of some ERC1155 NFT to caller&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT in layer 1. |
| _token | address | The address of ERC1155 NFT on layer 1. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _amounts | uint256[] | The list of corresponding number of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -43,8 +43,8 @@ Deposit a list of some ERC1155 NFT to a recipient&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT in layer 1. |
| _to | address | The address of recipient in layer 2. |
| _token | address | The address of ERC1155 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _amounts | uint256[] | The list of corresponding number of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -80,8 +80,8 @@ Deposit some ERC1155 NFT to a recipient&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT in layer 1. |
| _to | address | The address of recipient in layer 2. |
| _token | address | The address of ERC1155 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenId | uint256 | The token id to deposit. |
| _amount | uint256 | The amount of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -100,7 +100,7 @@ Deposit some ERC1155 NFT to caller&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC1155 NFT in layer 1. |
| _token | address | The address of ERC1155 NFT on layer 1. |
| _tokenId | uint256 | The token id to deposit. |
| _amount | uint256 | The amount of token to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -111,7 +111,7 @@ Deposit some ERC1155 NFT to caller&#39;s account on layer 2.
function finalizeBatchWithdrawERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds, uint256[] _amounts) external nonpayable
```
Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipient&#39;s account in layer 1. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC1155Gateway in layer 2.
Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipient&#39;s account on layer 1. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC1155Gateway on layer 2.
@@ -121,8 +121,8 @@ Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipie
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token in layer 2. |
| _to | address | The address of recipient in layer 1 to receive the token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
| _amounts | uint256[] | The list of corresponding number of token to withdraw. |
@@ -132,7 +132,7 @@ Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipie
function finalizeWithdrawERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId, uint256 _amount) external nonpayable
```
Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient&#39;s account in layer 1. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC1155Gateway in layer 2.
Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient&#39;s account on layer 1. The function should only be called by L1ScrollMessenger. The function should also only be called by L2ERC1155Gateway on layer 2.
@@ -142,8 +142,8 @@ Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient&#39
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token in layer 2. |
| _to | address | The address of recipient in layer 1 to receive the token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenId | uint256 | The token id to withdraw. |
| _amount | uint256 | The amount of token to withdraw. |
@@ -274,7 +274,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*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
@@ -368,8 +368,8 @@ Update layer 2 to layer 2 token mapping.
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding ERC1155 token in layer 2. |
| _l2Token | address | undefined |
| _l1Token | address | The address of ERC1155 token on layer 1. |
| _l2Token | address | The address of corresponding ERC1155 token on layer 2. |
@@ -381,7 +381,7 @@ Update layer 2 to layer 2 token mapping.
event BatchDepositERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds, uint256[] _amounts)
```
Emitted when the ERC1155 NFT is batch deposited to gateway in layer 1.
Emitted when the ERC1155 NFT is batch deposited to gateway on layer 1.
@@ -421,7 +421,7 @@ Emitted when some ERC1155 token is refunded.
event DepositERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId, uint256 _amount)
```
Emitted when the ERC1155 NFT is deposited to gateway in layer 1.
Emitted when the ERC1155 NFT is deposited to gateway on layer 1.
@@ -442,7 +442,7 @@ Emitted when the ERC1155 NFT is deposited to gateway in layer 1.
event FinalizeBatchWithdrawERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds, uint256[] _amounts)
```
Emitted when the ERC1155 NFT is batch transfered to recipient in layer 1.
Emitted when the ERC1155 NFT is batch transfered to recipient on layer 1.
@@ -463,7 +463,7 @@ Emitted when the ERC1155 NFT is batch transfered to recipient in layer 1.
event FinalizeWithdrawERC1155(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId, uint256 _amount)
```
Emitted when the ERC1155 NFT is transfered to recipient in layer 1.
Emitted when the ERC1155 NFT is transfered to recipient on layer 1.
@@ -478,6 +478,22 @@ Emitted when the ERC1155 NFT is transfered to recipient in layer 1.
| _tokenId | uint256 | undefined |
| _amount | uint256 | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
@@ -528,8 +544,8 @@ Emitted when token mapping for ERC1155 token is updated.
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding ERC1155 token in layer 2. |
| _l2Token | address | undefined |
| _l1Token | address | The address of ERC1155 token on layer 1. |
| _l2Token | address | The address of corresponding ERC1155 token on layer 2. |

View File

@@ -4,7 +4,7 @@
> L1ERC721Gateway
The `L1ERC721Gateway` is used to deposit ERC721 compatible NFT in layer 1 and finalize withdraw the NFTs from layer 2.
The `L1ERC721Gateway` is used to deposit ERC721 compatible NFT on layer 1 and finalize withdraw the NFTs from layer 2.
*The deposited NFTs are held in this gateway. On finalizing withdraw, the corresponding NFT will be transfer to the recipient directly. This will be changed if we have more specific scenarios.*
@@ -24,8 +24,8 @@ Deposit a list of some ERC721 NFT to a recipient&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 1. |
| _to | address | The address of recipient in layer 2. |
| _token | address | The address of ERC721 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -43,7 +43,7 @@ Deposit a list of some ERC721 NFT to caller&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 1. |
| _token | address | The address of ERC721 NFT on layer 1. |
| _tokenIds | uint256[] | The list of token ids to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -78,8 +78,8 @@ Deposit some ERC721 NFT to a recipient&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 1. |
| _to | address | The address of recipient in layer 2. |
| _token | address | The address of ERC721 NFT on layer 1. |
| _to | address | The address of recipient on layer 2. |
| _tokenId | uint256 | The token id to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -97,7 +97,7 @@ Deposit some ERC721 NFT to caller&#39;s account on layer 2.
| Name | Type | Description |
|---|---|---|
| _token | address | The address of ERC721 NFT in layer 1. |
| _token | address | The address of ERC721 NFT on layer 1. |
| _tokenId | uint256 | The token id to deposit. |
| _gasLimit | uint256 | Estimated gas limit required to complete the deposit on layer 2. |
@@ -107,9 +107,9 @@ Deposit some ERC721 NFT to caller&#39;s account on layer 2.
function finalizeBatchWithdrawERC721(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds) external nonpayable
```
Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s account in layer 1.
Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s account on layer 1.
*Requirements: - The function should only be called by L1ScrollMessenger. - The function should also only be called by L2ERC721Gateway in layer 2.*
*Requirements: - The function should only be called by L1ScrollMessenger. - The function should also only be called by L2ERC721Gateway on layer 2.*
#### Parameters
@@ -117,8 +117,8 @@ Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token in layer 2. |
| _to | address | The address of recipient in layer 1 to receive the token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenIds | uint256[] | The list of token ids to withdraw. |
### finalizeWithdrawERC721
@@ -127,9 +127,9 @@ Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient
function finalizeWithdrawERC721(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId) external nonpayable
```
Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s account in layer 1.
Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s account on layer 1.
*Requirements: - The function should only be called by L1ScrollMessenger. - The function should also only be called by L2ERC721Gateway in layer 2.*
*Requirements: - The function should only be called by L1ScrollMessenger. - The function should also only be called by L2ERC721Gateway on layer 2.*
#### Parameters
@@ -137,8 +137,8 @@ Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient&#39;s
|---|---|---|
| _l1Token | address | The address of corresponding layer 1 token. |
| _l2Token | address | The address of corresponding layer 2 token. |
| _from | address | The address of account who withdraw the token in layer 2. |
| _to | address | The address of recipient in layer 1 to receive the token. |
| _from | address | The address of account who withdraw the token on layer 2. |
| _to | address | The address of recipient on layer 1 to receive the token. |
| _tokenId | uint256 | The token id to withdraw. |
### initialize
@@ -241,7 +241,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*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
@@ -313,8 +313,8 @@ Update layer 2 to layer 2 token mapping.
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding ERC721 token in layer 2. |
| _l2Token | address | undefined |
| _l1Token | address | The address of ERC721 token on layer 1. |
| _l2Token | address | The address of corresponding ERC721 token on layer 2. |
@@ -326,7 +326,7 @@ Update layer 2 to layer 2 token mapping.
event BatchDepositERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds)
```
Emitted when the ERC721 NFT is batch deposited to gateway in layer 1.
Emitted when the ERC721 NFT is batch deposited to gateway on layer 1.
@@ -364,7 +364,7 @@ Emitted when a batch of ERC721 tokens are refunded.
event DepositERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId)
```
Emitted when the ERC721 NFT is deposited to gateway in layer 1.
Emitted when the ERC721 NFT is deposited to gateway on layer 1.
@@ -384,7 +384,7 @@ Emitted when the ERC721 NFT is deposited to gateway in layer 1.
event FinalizeBatchWithdrawERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256[] _tokenIds)
```
Emitted when the ERC721 NFT is batch transfered to recipient in layer 1.
Emitted when the ERC721 NFT is batch transfered to recipient on layer 1.
@@ -404,7 +404,7 @@ Emitted when the ERC721 NFT is batch transfered to recipient in layer 1.
event FinalizeWithdrawERC721(address indexed _l1Token, address indexed _l2Token, address indexed _from, address _to, uint256 _tokenId)
```
Emitted when the ERC721 NFT is transfered to recipient in layer 1.
Emitted when the ERC721 NFT is transfered to recipient on layer 1.
@@ -418,6 +418,22 @@ Emitted when the ERC721 NFT is transfered to recipient in layer 1.
| _to | address | undefined |
| _tokenId | uint256 | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
@@ -467,8 +483,8 @@ Emitted when token mapping for ERC721 token is updated.
| Name | Type | Description |
|---|---|---|
| _l1Token | address | The address of corresponding ERC721 token in layer 2. |
| _l2Token | address | undefined |
| _l1Token | address | The address of ERC721 token on layer 1. |
| _l2Token | address | The address of corresponding ERC721 token on layer 2. |

View File

@@ -320,7 +320,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### requestERC20
@@ -496,6 +496,22 @@ Emitted when ETH is withdrawn from L2 to L1 and transfer to recipient.
| amount | uint256 | undefined |
| data | bytes | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity

View File

@@ -89,7 +89,7 @@ Initialize the storage of L1ScrollMessenger.
function isL1MessageDropped(bytes32) external view returns (bool)
```
Mappging from L1 message hash to drop status.
Mapping from L1 message hash to drop status.
@@ -225,7 +225,7 @@ function prevReplayIndex(uint256) external view returns (uint256)
Mapping from queue index to previous replay queue index.
*If a message `x` was replayed 3 times with index `q1`, `q2` and `q3`, the value of `prevReplayIndex` and `replayStates` will be `replayStates[hash(x)].lastIndex = q3`, `replayStates[hash(x)].times = 3`, `prevReplayIndex[q3] = q2`, `prevReplayIndex[q2] = q1` and `prevReplayIndex[q1] = x`.*
*If a message `x` was replayed 3 times with index `q1`, `q2` and `q3`, the value of `prevReplayIndex` and `replayStates` will be `replayStates[hash(x)].lastIndex = q3`, `replayStates[hash(x)].times = 3`, `prevReplayIndex[q3] = q2`, `prevReplayIndex[q2] = q1`, `prevReplayIndex[q1] = x` and `prevReplayIndex[x]=nil`.The index `x` that `prevReplayIndex[x]=nil` is used as the termination of the list. Usually we use `0` to represent `nil`, but we cannot distinguish it with the first message with index zero. So a nonzero offset `1` is added to the value of `prevReplayIndex[x]` to avoid such situation.*
#### Parameters
@@ -268,7 +268,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### replayMessage
@@ -473,6 +473,22 @@ Emitted when a cross domain message is failed to relay.
|---|---|---|
| messageHash `indexed` | bytes32 | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity

View File

@@ -4,7 +4,7 @@
> L1StandardERC20Gateway
The `L1StandardERC20Gateway` is used to deposit standard ERC20 tokens in layer 1 and finalize withdraw the tokens from layer 2.
The `L1StandardERC20Gateway` is used to deposit standard ERC20 tokens on layer 1 and finalize withdraw the tokens from layer 2.
*The deposited ERC20 tokens are held in this gateway. On finalizing withdraw, the corresponding token will be transfer to the recipient directly. Any ERC20 that requires non-standard functionality should use a separate gateway.*
@@ -277,6 +277,22 @@ Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.
| amount | uint256 | undefined |
| data | bytes | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### RefundERC20
```solidity

View File

@@ -4,7 +4,7 @@
> L1WETHGateway
The `L1WETHGateway` contract is used to deposit `WETH` token in layer 1 and finalize withdraw `WETH` from layer 2.
The `L1WETHGateway` contract is used to deposit `WETH` token on layer 1 and finalize withdraw `WETH` from layer 2.
*The deposited WETH tokens are not held in the gateway. It will first be unwrapped as Ether and then the Ether will be sent to the `L1ScrollMessenger` contract. On finalizing withdraw, the Ether will be transfered from `L1ScrollMessenger`, then wrapped as WETH and finally transfer to recipient.*
@@ -275,6 +275,22 @@ Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.
| amount | uint256 | undefined |
| data | bytes | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### RefundERC20
```solidity

View File

@@ -4,7 +4,7 @@
> L2ERC1155Gateway
The `L2ERC1155Gateway` is used to withdraw ERC1155 compatible NFTs in layer 2 and finalize deposit the NFTs from layer 1.
The `L2ERC1155Gateway` is used to withdraw ERC1155 compatible NFTs on layer 2 and finalize deposit the NFTs from layer 1.
*The withdrawn NFTs tokens will be burned directly. On finalizing deposit, the corresponding NFT will be minted and transfered to the recipient. This will be changed if we have more specific scenarios.*
@@ -72,9 +72,9 @@ The address of corresponding L1/L2 Gateway contract.
function finalizeBatchDepositERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds, uint256[] _amounts) external nonpayable
```
Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account in layer 2.
Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway in layer 1.*
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway on layer 1.*
#### Parameters
@@ -93,9 +93,9 @@ Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s
function finalizeDepositERC1155(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId, uint256 _amount) external nonpayable
```
Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account in layer 2.
Complete ERC1155 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway in layer 1.*
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC1155Gateway on layer 1.*
#### Parameters
@@ -219,7 +219,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*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
@@ -313,8 +313,8 @@ Update layer 2 to layer 1 token mapping.
| Name | Type | Description |
|---|---|---|
| _l2Token | address | undefined |
| _l1Token | address | The address of 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
@@ -365,7 +365,7 @@ Withdraw some ERC1155 NFT to caller&#39;s account on layer 1.
event BatchWithdrawERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds, uint256[] amounts)
```
Emitted when the ERC1155 NFT is batch transfered to gateway in layer 2.
Emitted when the ERC1155 NFT is batch transfered to gateway on layer 2.
@@ -386,7 +386,7 @@ Emitted when the ERC1155 NFT is batch transfered to gateway in layer 2.
event FinalizeBatchDepositERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds, uint256[] amounts)
```
Emitted when the ERC1155 NFT is batch transfered to recipient in layer 2.
Emitted when the ERC1155 NFT is batch transfered to recipient on layer 2.
@@ -407,7 +407,7 @@ Emitted when the ERC1155 NFT is batch transfered to recipient in layer 2.
event FinalizeDepositERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId, uint256 amount)
```
Emitted when the ERC1155 NFT is transfered to recipient in layer 2.
Emitted when the ERC1155 NFT is transfered to recipient on layer 2.
@@ -422,6 +422,22 @@ Emitted when the ERC1155 NFT is transfered to recipient in layer 2.
| tokenId | uint256 | undefined |
| amount | uint256 | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
@@ -453,8 +469,8 @@ Emitted when token mapping for ERC1155 token is updated.
| Name | Type | Description |
|---|---|---|
| _l2Token | address | undefined |
| _l1Token | address | The address of 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
@@ -462,7 +478,7 @@ Emitted when token mapping for ERC1155 token is updated.
event WithdrawERC1155(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId, uint256 amount)
```
Emitted when the ERC1155 NFT is transfered to gateway in layer 2.
Emitted when the ERC1155 NFT is transfered to gateway on layer 2.

View File

@@ -4,7 +4,7 @@
> L2ERC721Gateway
The `L2ERC721Gateway` is used to withdraw ERC721 compatible NFTs in layer 2 and finalize deposit the NFTs from layer 1.
The `L2ERC721Gateway` is used to withdraw ERC721 compatible NFTs on layer 2 and finalize deposit the NFTs from layer 1.
*The withdrawn NFTs tokens will be burned directly. On finalizing deposit, the corresponding NFT will be minted and transfered to the recipient. This will be changed if we have more specific scenarios.*
@@ -70,9 +70,9 @@ The address of corresponding L1/L2 Gateway contract.
function finalizeBatchDepositERC721(address _l1Token, address _l2Token, address _from, address _to, uint256[] _tokenIds) external nonpayable
```
Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account in layer 2.
Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC721Gateway in layer 1.*
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC721Gateway on layer 1.*
#### Parameters
@@ -90,9 +90,9 @@ Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s
function finalizeDepositERC721(address _l1Token, address _l2Token, address _from, address _to, uint256 _tokenId) external nonpayable
```
Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account in layer 2.
Complete ERC721 deposit from layer 1 to layer 2 and send NFT to recipient&#39;s account on layer 2.
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC721Gateway in layer 1.*
*Requirements: - The function should only be called by L2ScrollMessenger. - The function should also only be called by L1ERC721Gateway on layer 1.*
#### Parameters
@@ -188,7 +188,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*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
@@ -260,8 +260,8 @@ Update layer 2 to layer 1 token mapping.
| Name | Type | Description |
|---|---|---|
| _l2Token | address | undefined |
| _l1Token | address | The address of 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
@@ -310,7 +310,7 @@ Withdraw some ERC721 NFT to caller&#39;s account on layer 1.
event BatchWithdrawERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds)
```
Emitted when the ERC721 NFT is batch transfered to gateway in layer 2.
Emitted when the ERC721 NFT is batch transfered to gateway on layer 2.
@@ -330,7 +330,7 @@ Emitted when the ERC721 NFT is batch transfered to gateway in layer 2.
event FinalizeBatchDepositERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256[] tokenIds)
```
Emitted when the ERC721 NFT is batch transfered to recipient in layer 2.
Emitted when the ERC721 NFT is batch transfered to recipient on layer 2.
@@ -350,7 +350,7 @@ Emitted when the ERC721 NFT is batch transfered to recipient in layer 2.
event FinalizeDepositERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId)
```
Emitted when the ERC721 NFT is transfered to recipient in layer 2.
Emitted when the ERC721 NFT is transfered to recipient on layer 2.
@@ -364,6 +364,22 @@ Emitted when the ERC721 NFT is transfered to recipient in layer 2.
| to | address | undefined |
| tokenId | uint256 | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity
@@ -395,8 +411,8 @@ Emitted when token mapping for ERC721 token is updated.
| Name | Type | Description |
|---|---|---|
| _l2Token | address | undefined |
| _l1Token | address | The address of 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
@@ -404,7 +420,7 @@ Emitted when token mapping for ERC721 token is updated.
event WithdrawERC721(address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 tokenId)
```
Emitted when the ERC721 NFT is transfered to gateway in layer 2.
Emitted when the ERC721 NFT is transfered to gateway on layer 2.

View File

@@ -214,7 +214,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### setDefaultERC20Gateway
@@ -437,6 +437,22 @@ Emitted when ETH is deposited from L1 to L2 and transfer to recipient.
| amount | uint256 | undefined |
| data | bytes | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity

View File

@@ -6,27 +6,10 @@
The `L2ScrollMessenger` contract can: 1. send messages from layer 2 to layer 1; 2. relay messages from layer 1 layer 2; 3. drop expired message due to sequencer problems.
*It should be a predeployed contract in layer 2 and should hold infinite amount of Ether (Specifically, `uint256(-1)`), which can be initialized in Genesis Block.*
*It should be a predeployed contract on layer 2 and should hold infinite amount of Ether (Specifically, `uint256(-1)`), which can be initialized in Genesis Block.*
## Methods
### blockContainer
```solidity
function blockContainer() external view returns (address)
```
The contract contains the list of L1 blocks.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### counterpart
```solidity
@@ -55,23 +38,6 @@ The address of fee vault, collecting cross domain messaging fee.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |
### gasOracle
```solidity
function gasOracle() external view returns (address)
```
The address of L2MessageQueue.
#### Returns
| Name | Type | Description |
@@ -257,30 +223,9 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*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.*
### retryMessageWithProof
```solidity
function retryMessageWithProof(address _from, address _to, uint256 _value, uint256 _nonce, bytes _message, IL2ScrollMessenger.L1MessageProof _proof) external nonpayable
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| _from | address | undefined |
| _to | address | undefined |
| _value | uint256 | undefined |
| _nonce | uint256 | undefined |
| _message | bytes | undefined |
| _proof | IL2ScrollMessenger.L1MessageProof | undefined |
### sendMessage
```solidity
@@ -384,54 +329,6 @@ Update max failed execution times.
|---|---|---|
| _maxFailedExecutionTimes | uint256 | The new max failed execution times. |
### verifyMessageExecutionStatus
```solidity
function verifyMessageExecutionStatus(bytes32 _blockHash, bytes32 _msgHash, bytes _proof) external view returns (bool)
```
Check whether the message is executed in the corresponding L1 block.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _blockHash | bytes32 | The block hash where the message should in. |
| _msgHash | bytes32 | The hash of the message to check. |
| _proof | bytes | The encoded storage proof from eth_getProof. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | bool Return true is the message is executed in L1, otherwise return false. |
### verifyMessageInclusionStatus
```solidity
function verifyMessageInclusionStatus(bytes32 _blockHash, bytes32 _msgHash, bytes _proof) external view returns (bool)
```
Check whether the l1 message is included in the corresponding L1 block.
#### Parameters
| Name | Type | Description |
|---|---|---|
| _blockHash | bytes32 | The block hash where the message should in. |
| _msgHash | bytes32 | The hash of the message to check. |
| _proof | bytes | The encoded storage proof from eth_getProof. |
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | bool Return true is the message is included in L1, otherwise return false. |
### xDomainMessageSender
```solidity
@@ -469,6 +366,22 @@ Emitted when a cross domain message is failed to relay.
|---|---|---|
| messageHash `indexed` | bytes32 | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### OwnershipTransferred
```solidity

View File

@@ -4,7 +4,7 @@
> L2StandardERC20Gateway
The `L2StandardERC20Gateway` is used to withdraw standard ERC20 tokens in layer 2 and finalize deposit the tokens from layer 1.
The `L2StandardERC20Gateway` is used to withdraw standard ERC20 tokens on layer 2 and finalize deposit the tokens from layer 1.
*The withdrawn ERC20 tokens will be burned directly. On finalizing deposit, the corresponding token will be minted and transfered to the recipient. Any ERC20 that requires non-standard functionality should use a separate gateway.*
@@ -244,6 +244,22 @@ Emitted when ERC20 token is deposited from L1 to L2 and transfer to recipient.
| amount | uint256 | undefined |
| data | bytes | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### WithdrawERC20
```solidity

View File

@@ -4,7 +4,7 @@
> L2WETHGateway
The `L2WETHGateway` contract is used to withdraw `WETH` token in layer 2 and finalize deposit `WETH` from layer 1.
The `L2WETHGateway` contract is used to withdraw `WETH` token on layer 2 and finalize deposit `WETH` from layer 1.
*The WETH tokens are not held in the gateway. It will first be unwrapped as Ether and then the Ether will be sent to the `L2ScrollMessenger` contract. On finalizing deposit, the Ether will be transfered from `L2ScrollMessenger`, then wrapped as WETH and finally transfer to recipient.*
@@ -260,6 +260,22 @@ Emitted when ERC20 token is deposited from L1 to L2 and transfer to recipient.
| amount | uint256 | undefined |
| data | bytes | undefined |
### Initialized
```solidity
event Initialized(uint8 version)
```
#### Parameters
| Name | Type | Description |
|---|---|---|
| version | uint8 | undefined |
### WithdrawERC20
```solidity

View File

@@ -98,7 +98,7 @@ function renounceOwnership() external nonpayable
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*
*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.*
### transferOwnership
@@ -127,7 +127,7 @@ function transferOwnership(address newOwner) external nonpayable
event DeployToken(address indexed _l1Token, address indexed _l2Token)
```
Emitted when a l2 token is deployed.

View File

@@ -9,7 +9,7 @@ libraries = [] # a list of deploy
cache = true # whether to cache builds or not
force = true # whether to ignore the cache (clean build)
evm_version = 'london' # the evm version (by hardfork name)
solc_version = '0.8.10' # override for the solc version (setting this ignores `auto_detect_solc`)
solc_version = '0.8.16' # override for the solc version (setting this ignores `auto_detect_solc`)
optimizer = true # enable or disable the solc optimizer
optimizer_runs = 200 # the number of optimizer runs
verbosity = 2 # the verbosity of tests

View File

@@ -22,7 +22,7 @@ const RINKEBY_PRIVATE_KEY = process.env.RINKEBY_PRIVATE_KEY || "1".repeat(64);
const L1_DEPLOYER_PRIVATE_KEY = process.env.L1_DEPLOYER_PRIVATE_KEY || "1".repeat(64);
const L2_DEPLOYER_PRIVATE_KEY = process.env.L2_DEPLOYER_PRIVATE_KEY || "1".repeat(64);
const SOLC_DEFAULT = "0.8.10";
const SOLC_DEFAULT = "0.8.16";
// try use forge config
let foundry: any;
@@ -116,7 +116,7 @@ const config: HardhatUserConfig = {
"IL2ERC1155Gateway",
"IScrollStandardERC20Factory",
"IZKRollup",
"WETH9",
"WrappedEther",
],
},
};

View File

@@ -1,10 +1,11 @@
/* eslint-disable node/no-unpublished-import */
/* eslint-disable node/no-missing-import */
import { expect } from "chai";
import { BigNumberish, BytesLike, constants, utils } from "ethers";
import { BigNumberish, BytesLike, constants } from "ethers";
import { ethers } from "hardhat";
import { EnforcedTxGateway, L1MessageQueue, L2GasPriceOracle, MockCaller } from "../typechain";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { arrayify } from "ethers/lib/utils";
describe("EnforcedTxGateway.spec", async () => {
let deployer: SignerWithAddress;
@@ -16,19 +17,36 @@ describe("EnforcedTxGateway.spec", async () => {
let oracle: L2GasPriceOracle;
let queue: L1MessageQueue;
const deployProxy = async (name: string, admin: string): Promise<string> => {
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const Factory = await ethers.getContractFactory(name, deployer);
const impl = await Factory.deploy();
await impl.deployed();
const proxy = await TransparentUpgradeableProxy.deploy(impl.address, admin, "0x");
await proxy.deployed();
return proxy.address;
};
beforeEach(async () => {
[deployer, feeVault, signer] = await ethers.getSigners();
const L1MessageQueue = await ethers.getContractFactory("L1MessageQueue", deployer);
queue = await L1MessageQueue.deploy();
await queue.deployed();
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
const admin = await ProxyAdmin.deploy();
await admin.deployed();
const L2GasPriceOracle = await ethers.getContractFactory("L2GasPriceOracle", deployer);
oracle = await L2GasPriceOracle.deploy();
queue = await ethers.getContractAt("L1MessageQueue", await deployProxy("L1MessageQueue", admin.address), deployer);
const EnforcedTxGateway = await ethers.getContractFactory("EnforcedTxGateway", deployer);
gateway = await EnforcedTxGateway.deploy();
await gateway.deployed();
oracle = await ethers.getContractAt(
"L2GasPriceOracle",
await deployProxy("L2GasPriceOracle", admin.address),
deployer
);
gateway = await ethers.getContractAt(
"EnforcedTxGateway",
await deployProxy("EnforcedTxGateway", admin.address),
deployer
);
const MockCaller = await ethers.getContractFactory("MockCaller", deployer);
caller = await MockCaller.deploy();
@@ -77,16 +95,16 @@ describe("EnforcedTxGateway.spec", async () => {
});
});
context("#setPaused", async () => {
context("#setPause", async () => {
it("should revert, when non-owner call", async () => {
await expect(gateway.connect(signer).setPaused(false)).to.revertedWith("Ownable: caller is not the owner");
await expect(gateway.connect(signer).setPause(false)).to.revertedWith("Ownable: caller is not the owner");
});
it("should succeed", async () => {
expect(await gateway.paused()).to.eq(false);
await expect(gateway.setPaused(true)).to.emit(gateway, "Paused").withArgs(deployer.address);
await expect(gateway.setPause(true)).to.emit(gateway, "Paused").withArgs(deployer.address);
expect(await gateway.paused()).to.eq(true);
await expect(gateway.setPaused(false)).to.emit(gateway, "Unpaused").withArgs(deployer.address);
await expect(gateway.setPause(false)).to.emit(gateway, "Unpaused").withArgs(deployer.address);
expect(await gateway.paused()).to.eq(false);
});
});
@@ -94,7 +112,7 @@ describe("EnforcedTxGateway.spec", async () => {
context("#sendTransaction, by EOA", async () => {
it("should revert, when contract is paused", async () => {
await gateway.setPaused(true);
await gateway.setPause(true);
await expect(
gateway.connect(signer)["sendTransaction(address,uint256,uint256,bytes)"](signer.address, 0, 0, "0x")
).to.revertedWith("Pausable: paused");
@@ -172,40 +190,109 @@ describe("EnforcedTxGateway.spec", async () => {
value: BigNumberish,
gasLimit: BigNumberish,
data: BytesLike
): Promise<string> => {
const queueIndex = await queue.nextCrossDomainMessageIndex();
const txHash = await queue.computeTransactionHash(signer.address, queueIndex, value, target, gasLimit, data);
return await signer.signMessage(utils.arrayify(txHash));
) => {
const enforcedTx = {
sender: signer.address,
target: target,
value: value,
gasLimit: gasLimit,
data: arrayify(data),
nonce: await gateway.nonces(signer.address),
deadline: constants.MaxUint256,
};
const domain = {
name: "EnforcedTxGateway",
version: "1",
chainId: (await ethers.provider.getNetwork()).chainId,
verifyingContract: gateway.address,
};
const types = {
EnforcedTransaction: [
{
name: "sender",
type: "address",
},
{
name: "target",
type: "address",
},
{
name: "value",
type: "uint256",
},
{
name: "gasLimit",
type: "uint256",
},
{
name: "data",
type: "bytes",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
type: "uint256",
},
],
};
const signature = await signer._signTypedData(domain, types, enforcedTx);
return signature;
};
it("should revert, when contract is paused", async () => {
await gateway.setPaused(true);
await gateway.setPause(true);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
0,
"0x",
constants.MaxUint256,
"0x",
constants.AddressZero
)
).to.revertedWith("Pausable: paused");
});
it("should revert, when signature expired", async () => {
const timestamp = (await ethers.provider.getBlock("latest")).timestamp;
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
0,
"0x",
timestamp - 1,
"0x",
constants.AddressZero
)
).to.revertedWith("signature expired");
});
it("should revert, when signature is wrong", async () => {
const signature = await signer.signMessage("0x00");
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
0,
"0x",
constants.MaxUint256,
signature,
constants.AddressZero
)
@@ -218,12 +305,13 @@ describe("EnforcedTxGateway.spec", async () => {
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
1000000,
"0x",
constants.MaxUint256,
signature,
signer.address,
{ value: fee.sub(1) }
@@ -238,12 +326,13 @@ describe("EnforcedTxGateway.spec", async () => {
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
1000000,
"0x",
constants.MaxUint256,
signature,
signer.address,
{ value: fee }
@@ -255,15 +344,17 @@ describe("EnforcedTxGateway.spec", async () => {
const signature = await getSignature(signer, deployer.address, 0, 1000000, "0x");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
const feeVaultBalanceBefore = await ethers.provider.getBalance(feeVault.address);
expect(await gateway.nonces(signer.address)).to.eq(0);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
constants.MaxUint256,
signature,
signer.address,
{ value: fee }
@@ -271,8 +362,26 @@ describe("EnforcedTxGateway.spec", async () => {
)
.to.emit(queue, "QueueTransaction")
.withArgs(signer.address, deployer.address, 0, 0, 1000000, "0x");
expect(await gateway.nonces(signer.address)).to.eq(1);
const feeVaultBalanceAfter = await ethers.provider.getBalance(feeVault.address);
expect(feeVaultBalanceAfter.sub(feeVaultBalanceBefore)).to.eq(fee);
// use the same nonce to sign should fail
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
constants.MaxUint256,
signature,
signer.address,
{ value: fee }
)
).to.revertedWith("Incorrect signature");
});
it("should succeed, with refund", async () => {
@@ -280,15 +389,17 @@ describe("EnforcedTxGateway.spec", async () => {
const fee = await queue.estimateCrossDomainMessageFee(1000000);
const feeVaultBalanceBefore = await ethers.provider.getBalance(feeVault.address);
const signerBalanceBefore = await ethers.provider.getBalance(signer.address);
expect(await gateway.nonces(signer.address)).to.eq(0);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
constants.MaxUint256,
signature,
signer.address,
{ value: fee.add(100) }
@@ -296,24 +407,43 @@ describe("EnforcedTxGateway.spec", async () => {
)
.to.emit(queue, "QueueTransaction")
.withArgs(signer.address, deployer.address, 0, 0, 1000000, "0x");
expect(await gateway.nonces(signer.address)).to.eq(1);
const feeVaultBalanceAfter = await ethers.provider.getBalance(feeVault.address);
const signerBalanceAfter = await ethers.provider.getBalance(signer.address);
expect(feeVaultBalanceAfter.sub(feeVaultBalanceBefore)).to.eq(fee);
expect(signerBalanceAfter.sub(signerBalanceBefore)).to.eq(100);
// use the same nonce to sign should fail
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
deployer.address,
0,
1000000,
"0x",
constants.MaxUint256,
signature,
signer.address,
{ value: fee.add(100) }
)
).to.revertedWith("Incorrect signature");
});
it("should revert, when refund failed", async () => {
const signature = await getSignature(signer, signer.address, 0, 1000000, "0x");
const signature = await getSignature(signer, signer.address, 0, 1000000, "0x1234");
const fee = await queue.estimateCrossDomainMessageFee(1000000);
await expect(
gateway
.connect(deployer)
["sendTransaction(address,address,uint256,uint256,bytes,bytes,address)"](
["sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)"](
signer.address,
signer.address,
0,
1000000,
"0x",
"0x1234",
constants.MaxUint256,
signature,
gateway.address,
{ value: fee.add(100) }

View File

@@ -119,10 +119,16 @@ describe("L1BlockContainer", async () => {
const [deployer] = await ethers.getSigners();
const L1BlockContainer = await ethers.getContractFactory("L1BlockContainer", deployer);
container = await L1BlockContainer.deploy(deployer.address);
const Whitelist = await ethers.getContractFactory("Whitelist", deployer);
const whitelist = await Whitelist.deploy(deployer.address);
await whitelist.updateWhitelistStatus([deployer.address], true);
await container.updateWhitelist(whitelist.address);
});
it("should revert, when sender not allowed", async () => {
const [deployer] = await ethers.getSigners();
const [, signer] = await ethers.getSigners();
await container.initialize(
test.parentHash,
test.blockHeight - 1,
@@ -130,11 +136,8 @@ describe("L1BlockContainer", async () => {
test.baseFee,
test.stateRoot
);
const Whitelist = await ethers.getContractFactory("Whitelist", deployer);
const whitelist = await Whitelist.deploy(deployer.address);
await container.updateWhitelist(whitelist.address);
await expect(container.importBlockHeader(constants.HashZero, [], false)).to.revertedWith(
await expect(container.connect(signer).importBlockHeader(constants.HashZero, [], false)).to.revertedWith(
"Not whitelisted sender"
);
});

View File

@@ -17,15 +17,30 @@ describe("L1MessageQueue", async () => {
let oracle: L2GasPriceOracle;
let queue: L1MessageQueue;
const deployProxy = async (name: string, admin: string): Promise<string> => {
const TransparentUpgradeableProxy = await ethers.getContractFactory("TransparentUpgradeableProxy", deployer);
const Factory = await ethers.getContractFactory(name, deployer);
const impl = await Factory.deploy();
await impl.deployed();
const proxy = await TransparentUpgradeableProxy.deploy(impl.address, admin, "0x");
await proxy.deployed();
return proxy.address;
};
beforeEach(async () => {
[deployer, scrollChain, messenger, gateway, signer] = await ethers.getSigners();
const L1MessageQueue = await ethers.getContractFactory("L1MessageQueue", deployer);
queue = await L1MessageQueue.deploy();
await queue.deployed();
const ProxyAdmin = await ethers.getContractFactory("ProxyAdmin", deployer);
const admin = await ProxyAdmin.deploy();
await admin.deployed();
const L2GasPriceOracle = await ethers.getContractFactory("L2GasPriceOracle", deployer);
oracle = await L2GasPriceOracle.deploy();
queue = await ethers.getContractAt("L1MessageQueue", await deployProxy("L1MessageQueue", admin.address), deployer);
oracle = await ethers.getContractAt(
"L2GasPriceOracle",
await deployProxy("L2GasPriceOracle", admin.address),
deployer
);
await oracle.initialize(21000, 0, 8, 16);
await queue.initialize(messenger.address, scrollChain.address, gateway.address, oracle.address, 10000000);

View File

@@ -55,8 +55,8 @@
"typescript": "^4.5.2"
},
"dependencies": {
"@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2"
"@openzeppelin/contracts": "^v4.9.2",
"@openzeppelin/contracts-upgradeable": "^v4.9.2"
},
"lint-staged": {
"*.{js,ts}": "npx eslint --cache --fix",

View File

@@ -10,8 +10,8 @@ async function main() {
if (!addressFile.get("WETH")) {
console.log(">> Deploy WETH");
const WETH9 = await ethers.getContractFactory("WETH9", deployer);
const weth = await WETH9.deploy();
const WrappedEther = await ethers.getContractFactory("WrappedEther", deployer);
const weth = await WrappedEther.deploy();
console.log(`>> waiting for transaction: ${weth.deployTransaction.hash}`);
await weth.deployed();
console.log(`✅ WETH deployed at ${weth.address}`);

View File

@@ -15,7 +15,6 @@ import {L2GatewayRouter} from "../../src/L2/gateways/L2GatewayRouter.sol";
import {L2ScrollMessenger} from "../../src/L2/L2ScrollMessenger.sol";
import {L2StandardERC20Gateway} from "../../src/L2/gateways/L2StandardERC20Gateway.sol";
import {L2WETHGateway} from "../../src/L2/gateways/L2WETHGateway.sol";
import {L1BlockContainer} from "../../src/L2/predeploys/L1BlockContainer.sol";
import {L1GasPriceOracle} from "../../src/L2/predeploys/L1GasPriceOracle.sol";
import {L2MessageQueue} from "../../src/L2/predeploys/L2MessageQueue.sol";
import {L2TxFeeVault} from "../../src/L2/predeploys/L2TxFeeVault.sol";
@@ -31,12 +30,10 @@ contract DeployL2BridgeContracts is Script {
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
L1GasPriceOracle oracle;
L1BlockContainer container;
L2MessageQueue queue;
ProxyAdmin proxyAdmin;
// predeploy contracts
address L1_BLOCK_CONTAINER_PREDEPLOY_ADDR = vm.envOr("L1_BLOCK_CONTAINER_PREDEPLOY_ADDR", address(0));
address L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR = vm.envOr("L1_GAS_PRICE_ORACLE_PREDEPLOY_ADDR", address(0));
address L2_MESSAGE_QUEUE_PREDEPLOY_ADDR = vm.envOr("L2_MESSAGE_QUEUE_PREDEPLOY_ADDR", address(0));
address L2_TX_FEE_VAULT_PREDEPLOY_ADDR = vm.envOr("L2_TX_FEE_VAULT_PREDEPLOY_ADDR", address(0));
@@ -47,7 +44,6 @@ contract DeployL2BridgeContracts is Script {
// predeploys
deployL1GasPriceOracle();
deployL1BlockContainer();
deployL2MessageQueue();
deployTxFeeVault();
deployL2Whitelist();
@@ -80,19 +76,6 @@ contract DeployL2BridgeContracts is Script {
logAddress("L1_GAS_PRICE_ORACLE_ADDR", address(oracle));
}
function deployL1BlockContainer() internal {
if (L1_BLOCK_CONTAINER_PREDEPLOY_ADDR != address(0)) {
container = L1BlockContainer(L1_BLOCK_CONTAINER_PREDEPLOY_ADDR);
logAddress("L1_BLOCK_CONTAINER_ADDR", address(L1_BLOCK_CONTAINER_PREDEPLOY_ADDR));
return;
}
address owner = vm.addr(L2_DEPLOYER_PRIVATE_KEY);
container = new L1BlockContainer(owner);
logAddress("L1_BLOCK_CONTAINER_ADDR", address(container));
}
function deployL2MessageQueue() internal {
if (L2_MESSAGE_QUEUE_PREDEPLOY_ADDR != address(0)) {
queue = L2MessageQueue(L2_MESSAGE_QUEUE_PREDEPLOY_ADDR);
@@ -137,7 +120,7 @@ contract DeployL2BridgeContracts is Script {
}
function deployL2ScrollMessenger() internal {
L2ScrollMessenger impl = new L2ScrollMessenger(address(container), address(oracle), address(queue));
L2ScrollMessenger impl = new L2ScrollMessenger(address(queue));
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(proxyAdmin),

View File

@@ -1,30 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
import { Script } from "forge-std/Script.sol";
import { console } from "forge-std/console.sol";
import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";
import { WETH9 } from "../../src/L2/predeploys/WETH9.sol";
import {WrappedEther} from "../../src/L2/predeploys/WrappedEther.sol";
contract DeployWeth is Script {
address L1_WETH_ADDR = vm.envAddress("L1_WETH_ADDR");
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
address L1_WETH_ADDR = vm.envAddress("L1_WETH_ADDR");
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
function run() external {
// deploy weth only if we're running a private L1 network
if (L1_WETH_ADDR == address(0)) {
uint256 L1_WETH_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_WETH_DEPLOYER_PRIVATE_KEY");
vm.startBroadcast(L1_WETH_DEPLOYER_PRIVATE_KEY);
WETH9 weth = new WETH9();
L1_WETH_ADDR = address(weth);
vm.stopBroadcast();
function run() external {
// deploy weth only if we're running a private L1 network
if (L1_WETH_ADDR == address(0)) {
uint256 L1_WETH_DEPLOYER_PRIVATE_KEY = vm.envUint("L1_WETH_DEPLOYER_PRIVATE_KEY");
vm.startBroadcast(L1_WETH_DEPLOYER_PRIVATE_KEY);
WrappedEther weth = new WrappedEther();
L1_WETH_ADDR = address(weth);
vm.stopBroadcast();
}
logAddress("L1_WETH_ADDR", L1_WETH_ADDR);
logAddress("L2_WETH_ADDR", L2_WETH_ADDR);
}
logAddress("L1_WETH_ADDR", L1_WETH_ADDR);
logAddress("L2_WETH_ADDR", L2_WETH_ADDR);
}
function logAddress(string memory name, address addr) internal view {
console.log(string(abi.encodePacked(name, "=", vm.toString(address(addr)))));
}
function logAddress(string memory name, address addr) internal view {
console.log(string(abi.encodePacked(name, "=", vm.toString(address(addr)))));
}
}

View File

@@ -22,8 +22,8 @@ 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");
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");
address L1_WHITELIST_ADDR = vm.envAddress("L1_WHITELIST_ADDR");
address L1_SCROLL_CHAIN_PROXY_ADDR = vm.envAddress("L1_SCROLL_CHAIN_PROXY_ADDR");
@@ -61,9 +61,15 @@ contract InitializeL1BridgeContracts is Script {
MAX_L2_TX_IN_CHUNK
);
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(0, 0, 0, 0);
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).initialize(
21000, // _txGas
53000, // _txGasContractCreation
4, // _zeroGas
16 // _nonZeroGas
);
L2GasPriceOracle(L2_GAS_PRICE_ORACLE_PROXY_ADDR).updateWhitelist(L1_WHITELIST_ADDR);
// initialize L1MessageQueue
@@ -137,6 +143,15 @@ contract InitializeL1BridgeContracts is Script {
L1_SCROLL_MESSENGER_PROXY_ADDR
);
// set WETH gateway in router
{
address[] memory _tokens = new address[](1);
_tokens[0] = L1_WETH_ADDR;
address[] memory _gateways = new address[](1);
_gateways[0] = L1_WETH_GATEWAY_PROXY_ADDR;
L1GatewayRouter(L1_GATEWAY_ROUTER_PROXY_ADDR).setERC20Gateway(_tokens, _gateways);
}
vm.stopBroadcast();
}
}

View File

@@ -13,7 +13,6 @@ import {L2StandardERC20Gateway} from "../../src/L2/gateways/L2StandardERC20Gatew
import {L2WETHGateway} from "../../src/L2/gateways/L2WETHGateway.sol";
import {L2MessageQueue} from "../../src/L2/predeploys/L2MessageQueue.sol";
import {L2TxFeeVault} from "../../src/L2/predeploys/L2TxFeeVault.sol";
import {L1BlockContainer} from "../../src/L2/predeploys/L1BlockContainer.sol";
import {L1GasPriceOracle} from "../../src/L2/predeploys/L1GasPriceOracle.sol";
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
@@ -21,6 +20,8 @@ import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStanda
contract InitializeL2BridgeContracts is Script {
uint256 deployerPrivateKey = vm.envUint("L2_DEPLOYER_PRIVATE_KEY");
address L2_WETH_ADDR = vm.envAddress("L2_WETH_ADDR");
address L1_SCROLL_MESSENGER_PROXY_ADDR = vm.envAddress("L1_SCROLL_MESSENGER_PROXY_ADDR");
address L1_GATEWAY_ROUTER_PROXY_ADDR = vm.envAddress("L1_GATEWAY_ROUTER_PROXY_ADDR");
address L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR = vm.envAddress("L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR");
@@ -31,7 +32,6 @@ contract InitializeL2BridgeContracts is Script {
address L1_WETH_GATEWAY_PROXY_ADDR = vm.envAddress("L1_WETH_GATEWAY_PROXY_ADDR");
address L2_TX_FEE_VAULT_ADDR = vm.envAddress("L2_TX_FEE_VAULT_ADDR");
address L1_BLOCK_CONTAINER_ADDR = vm.envAddress("L1_BLOCK_CONTAINER_ADDR");
address L1_GAS_PRICE_ORACLE_ADDR = vm.envAddress("L1_GAS_PRICE_ORACLE_ADDR");
address L2_WHITELIST_ADDR = vm.envAddress("L2_WHITELIST_ADDR");
address L2_MESSAGE_QUEUE_ADDR = vm.envAddress("L2_MESSAGE_QUEUE_ADDR");
@@ -50,15 +50,11 @@ contract InitializeL2BridgeContracts is Script {
vm.startBroadcast(deployerPrivateKey);
// initialize L2MessageQueue
L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).initialize();
L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).updateMessenger(L2_SCROLL_MESSENGER_PROXY_ADDR);
L2MessageQueue(L2_MESSAGE_QUEUE_ADDR).initialize(L2_SCROLL_MESSENGER_PROXY_ADDR);
// initialize L2TxFeeVault
L2TxFeeVault(payable(L2_TX_FEE_VAULT_ADDR)).updateMessenger(L2_SCROLL_MESSENGER_PROXY_ADDR);
// initialize L1BlockContainer
L1BlockContainer(L1_BLOCK_CONTAINER_ADDR).updateWhitelist(L2_WHITELIST_ADDR);
// initialize L1GasPriceOracle
L1GasPriceOracle(L1_GAS_PRICE_ORACLE_ADDR).updateWhitelist(L2_WHITELIST_ADDR);
@@ -115,6 +111,15 @@ contract InitializeL2BridgeContracts is Script {
L2_SCROLL_MESSENGER_PROXY_ADDR
);
// set WETH gateway in router
{
address[] memory _tokens = new address[](1);
_tokens[0] = L2_WETH_ADDR;
address[] memory _gateways = new address[](1);
_gateways[0] = L2_WETH_GATEWAY_PROXY_ADDR;
L2GatewayRouter(L2_GATEWAY_ROUTER_PROXY_ADDR).setERC20Gateway(_tokens, _gateways);
}
// initialize ScrollStandardERC20Factory
ScrollStandardERC20Factory(L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR).transferOwnership(
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity =0.8.16;
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
import {IScrollMessenger} from "../libraries/IScrollMessenger.sol";

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity =0.8.16;
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
@@ -82,6 +82,10 @@ contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1Scrol
* Constructor *
***************/
constructor() {
_disableInitializers();
}
/// @notice Initialize the storage of L1ScrollMessenger.
/// @param _counterpart The address of L2ScrollMessenger contract in L2.
/// @param _feeVault The address of fee vault, which will be used to collect relayer fee.
@@ -178,8 +182,8 @@ contract L1ScrollMessenger is PausableUpgradeable, ScrollMessengerBase, IL1Scrol
address _refundAddress
) external payable override whenNotPaused notInExecution {
// We will use a different `queueIndex` for the replaced message. However, the original `queueIndex` or `nonce`
// is encoded in the `_message`. We will check the `xDomainCalldata` in layer 2 to avoid duplicated execution.
// So, only one message will succeed in layer 2. If one of the message is executed successfully, the other one
// is encoded in the `_message`. We will check the `xDomainCalldata` on layer 2 to avoid duplicated execution.
// So, only one message will succeed on layer 2. If one of the message is executed successfully, the other one
// will revert with "Message was already successfully executed".
address _messageQueue = messageQueue;
address _counterpart = counterpart;

View File

@@ -1,15 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ECDSAUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
import {EIP712Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {IL1MessageQueue} from "../rollup/IL1MessageQueue.sol";
contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable {
// solhint-disable reason-string
contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable, EIP712Upgradeable {
/**********
* Events *
**********/
@@ -19,6 +22,16 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
/// @param _newFeeVault The address of new fee vault contract.
event UpdateFeeVault(address _oldFeeVault, address _newFeeVault);
/*************
* Constants *
*************/
// solhint-disable-next-line var-name-mixedcase
bytes32 private constant _ENFORCED_TX_TYPEHASH =
keccak256(
"EnforcedTransaction(address sender,address target,uint256 value,uint256 gasLimit,bytes data,uint256 nonce,uint256 deadline)"
);
/*************
* Variables *
*************/
@@ -29,19 +42,39 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
/// @notice The address of fee vault contract.
address public feeVault;
/// @notice Mapping from EOA address to current nonce.
/// @dev Every successful call to `sendTransaction` with signature increases `_sender`'s nonce by one.
/// This prevents a signature from being used multiple times.
mapping(address => uint256) public nonces;
/***************
* Constructor *
***************/
constructor() {
_disableInitializers();
}
function initialize(address _queue, address _feeVault) external initializer {
OwnableUpgradeable.__Ownable_init();
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();
PausableUpgradeable.__Pausable_init();
EIP712Upgradeable.__EIP712_init("EnforcedTxGateway", "1");
messageQueue = _queue;
feeVault = _feeVault;
}
/*************************
* Public View Functions *
*************************/
/// @notice return the domain separator for the typed transaction
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _domainSeparatorV4();
}
/*****************************
* Public Mutating Functions *
*****************************/
@@ -58,6 +91,7 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
uint256 _gasLimit,
bytes calldata _data
) external payable whenNotPaused {
// solhint-disable-next-line avoid-tx-origin
require(msg.sender == tx.origin, "Only EOA senders are allowed to send enforced transaction");
_sendTransaction(msg.sender, _target, _value, _gasLimit, _data, msg.sender);
@@ -70,6 +104,7 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
/// @param _value The value passed
/// @param _gasLimit The maximum gas should be used for this transaction in L2.
/// @param _data The calldata passed to target contract.
/// @param _deadline The deadline of the signature.
/// @param _signature The signature for the transaction.
/// @param _refundAddress The address to refund exceeded fee.
function sendTransaction(
@@ -78,22 +113,23 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
uint256 _value,
uint256 _gasLimit,
bytes calldata _data,
uint256 _deadline,
bytes memory _signature,
address _refundAddress
) external payable whenNotPaused {
address _messageQueue = messageQueue;
uint256 _queueIndex = IL1MessageQueue(messageQueue).nextCrossDomainMessageIndex();
bytes32 _txHash = IL1MessageQueue(_messageQueue).computeTransactionHash(
_sender,
_queueIndex,
_value,
_target,
_gasLimit,
_data
);
// solhint-disable-next-line not-rely-on-time
require(block.timestamp <= _deadline, "signature expired");
bytes32 _signHash = ECDSAUpgradeable.toEthSignedMessageHash(_txHash);
address _signer = ECDSAUpgradeable.recover(_signHash, _signature);
uint256 _nonce = nonces[_sender];
bytes32 _structHash = keccak256(
abi.encode(_ENFORCED_TX_TYPEHASH, _sender, _target, _value, _gasLimit, keccak256(_data), _nonce, _deadline)
);
unchecked {
nonces[_sender] = _nonce + 1;
}
bytes32 _hash = _hashTypedDataV4(_structHash);
address _signer = ECDSAUpgradeable.recover(_hash, _signature);
// no need to check `_signer != address(0)`, since it is checked in `recover`.
require(_signer == _sender, "Incorrect signature");
@@ -116,7 +152,7 @@ contract EnforcedTxGateway is OwnableUpgradeable, ReentrancyGuardUpgradeable, Pa
/// @notice Pause or unpause this contract.
/// @param _status Pause this contract if it is true, otherwise unpause this contract.
function setPaused(bool _status) external onlyOwner {
function setPause(bool _status) external onlyOwner {
if (_status) {
_pause();
} else {

View File

@@ -1,18 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
/// @title The interface for the ERC1155 cross chain gateway in layer 1.
/// @title The interface for the ERC1155 cross chain gateway on layer 1.
interface IL1ERC1155Gateway {
/**********
* Events *
**********/
/// @notice Emitted when the ERC1155 NFT is transfered to recipient in layer 1.
/// @param _l1Token The address of ERC1155 NFT in layer 1.
/// @param _l2Token The address of ERC1155 NFT in layer 2.
/// @param _from The address of sender in layer 2.
/// @param _to The address of recipient in layer 1.
/// @notice Emitted when the ERC1155 NFT is transfered to recipient on layer 1.
/// @param _l1Token The address of ERC1155 NFT on layer 1.
/// @param _l2Token The address of ERC1155 NFT on layer 2.
/// @param _from The address of sender on layer 2.
/// @param _to The address of recipient on layer 1.
/// @param _tokenId The token id of the ERC1155 NFT to withdraw from layer 2.
/// @param _amount The number of token to withdraw from layer 2.
event FinalizeWithdrawERC1155(
@@ -24,11 +24,11 @@ interface IL1ERC1155Gateway {
uint256 _amount
);
/// @notice Emitted when the ERC1155 NFT is batch transfered to recipient in layer 1.
/// @param _l1Token The address of ERC1155 NFT in layer 1.
/// @param _l2Token The address of ERC1155 NFT in layer 2.
/// @param _from The address of sender in layer 2.
/// @param _to The address of recipient in layer 1.
/// @notice Emitted when the ERC1155 NFT is batch transfered to recipient on layer 1.
/// @param _l1Token The address of ERC1155 NFT on layer 1.
/// @param _l2Token The address of ERC1155 NFT on layer 2.
/// @param _from The address of sender on layer 2.
/// @param _to The address of recipient on layer 1.
/// @param _tokenIds The list of token ids of the ERC1155 NFT to withdraw from layer 2.
/// @param _amounts The list of corresponding number of token to withdraw from layer 2.
event FinalizeBatchWithdrawERC1155(
@@ -40,13 +40,13 @@ interface IL1ERC1155Gateway {
uint256[] _amounts
);
/// @notice Emitted when the ERC1155 NFT is deposited to gateway in layer 1.
/// @param _l1Token The address of ERC1155 NFT in layer 1.
/// @param _l2Token The address of ERC1155 NFT in layer 2.
/// @param _from The address of sender in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _tokenId The token id of the ERC1155 NFT to deposit in layer 1.
/// @param _amount The number of token to deposit in layer 1.
/// @notice Emitted when the ERC1155 NFT is deposited to gateway on layer 1.
/// @param _l1Token The address of ERC1155 NFT on layer 1.
/// @param _l2Token The address of ERC1155 NFT on layer 2.
/// @param _from The address of sender on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenId The token id of the ERC1155 NFT to deposit on layer 1.
/// @param _amount The number of token to deposit on layer 1.
event DepositERC1155(
address indexed _l1Token,
address indexed _l2Token,
@@ -56,13 +56,13 @@ interface IL1ERC1155Gateway {
uint256 _amount
);
/// @notice Emitted when the ERC1155 NFT is batch deposited to gateway in layer 1.
/// @param _l1Token The address of ERC1155 NFT in layer 1.
/// @param _l2Token The address of ERC1155 NFT in layer 2.
/// @param _from The address of sender in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _tokenIds The list of token ids of the ERC1155 NFT to deposit in layer 1.
/// @param _amounts The list of corresponding number of token to deposit in layer 1.
/// @notice Emitted when the ERC1155 NFT is batch deposited to gateway on layer 1.
/// @param _l1Token The address of ERC1155 NFT on layer 1.
/// @param _l2Token The address of ERC1155 NFT on layer 2.
/// @param _from The address of sender on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenIds The list of token ids of the ERC1155 NFT to deposit on layer 1.
/// @param _amounts The list of corresponding number of token to deposit on layer 1.
event BatchDepositERC1155(
address indexed _l1Token,
address indexed _l2Token,
@@ -91,7 +91,7 @@ interface IL1ERC1155Gateway {
*************************/
/// @notice Deposit some ERC1155 NFT to caller's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
/// @param _token The address of ERC1155 NFT on layer 1.
/// @param _tokenId The token id to deposit.
/// @param _amount The amount of token to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
@@ -103,8 +103,8 @@ interface IL1ERC1155Gateway {
) external payable;
/// @notice Deposit some ERC1155 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC1155 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenId The token id to deposit.
/// @param _amount The amount of token to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
@@ -117,7 +117,7 @@ interface IL1ERC1155Gateway {
) external payable;
/// @notice Deposit a list of some ERC1155 NFT to caller's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
/// @param _token The address of ERC1155 NFT on layer 1.
/// @param _tokenIds The list of token ids to deposit.
/// @param _amounts The list of corresponding number of token to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
@@ -129,8 +129,8 @@ interface IL1ERC1155Gateway {
) external payable;
/// @notice Deposit a list of some ERC1155 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC1155 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenIds The list of token ids to deposit.
/// @param _amounts The list of corresponding number of token to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
@@ -142,13 +142,13 @@ interface IL1ERC1155Gateway {
uint256 _gasLimit
) external payable;
/// @notice Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient's account in layer 1.
/// @notice Complete ERC1155 withdraw from layer 2 to layer 1 and send fund to recipient's account on layer 1.
/// The function should only be called by L1ScrollMessenger.
/// The function should also only be called by L2ERC1155Gateway in layer 2.
/// The function should also only be called by L2ERC1155Gateway on layer 2.
/// @param _l1Token The address of corresponding layer 1 token.
/// @param _l2Token The address of corresponding layer 2 token.
/// @param _from The address of account who withdraw the token in layer 2.
/// @param _to The address of recipient in layer 1 to receive the token.
/// @param _from The address of account who withdraw the token on layer 2.
/// @param _to The address of recipient on layer 1 to receive the token.
/// @param _tokenId The token id to withdraw.
/// @param _amount The amount of token to withdraw.
function finalizeWithdrawERC1155(
@@ -160,13 +160,13 @@ interface IL1ERC1155Gateway {
uint256 _amount
) external;
/// @notice Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipient's account in layer 1.
/// @notice Complete ERC1155 batch withdraw from layer 2 to layer 1 and send fund to recipient's account on layer 1.
/// The function should only be called by L1ScrollMessenger.
/// The function should also only be called by L2ERC1155Gateway in layer 2.
/// The function should also only be called by L2ERC1155Gateway on layer 2.
/// @param _l1Token The address of corresponding layer 1 token.
/// @param _l2Token The address of corresponding layer 2 token.
/// @param _from The address of account who withdraw the token in layer 2.
/// @param _to The address of recipient in layer 1 to receive the token.
/// @param _from The address of account who withdraw the token on layer 2.
/// @param _to The address of recipient on layer 1 to receive the token.
/// @param _tokenIds The list of token ids to withdraw.
/// @param _amounts The list of corresponding number of token to withdraw.
function finalizeBatchWithdrawERC1155(

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
interface IL1ERC20Gateway {
/**********

View File

@@ -1,18 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
/// @title The interface for the ERC721 cross chain gateway in layer 1.
/// @title The interface for the ERC721 cross chain gateway on layer 1.
interface IL1ERC721Gateway {
/**********
* Events *
**********/
/// @notice Emitted when the ERC721 NFT is transfered to recipient in layer 1.
/// @param _l1Token The address of ERC721 NFT in layer 1.
/// @param _l2Token The address of ERC721 NFT in layer 2.
/// @param _from The address of sender in layer 2.
/// @param _to The address of recipient in layer 1.
/// @notice Emitted when the ERC721 NFT is transfered to recipient on layer 1.
/// @param _l1Token The address of ERC721 NFT on layer 1.
/// @param _l2Token The address of ERC721 NFT on layer 2.
/// @param _from The address of sender on layer 2.
/// @param _to The address of recipient on layer 1.
/// @param _tokenId The token id of the ERC721 NFT to withdraw from layer 2.
event FinalizeWithdrawERC721(
address indexed _l1Token,
@@ -22,11 +22,11 @@ interface IL1ERC721Gateway {
uint256 _tokenId
);
/// @notice Emitted when the ERC721 NFT is batch transfered to recipient in layer 1.
/// @param _l1Token The address of ERC721 NFT in layer 1.
/// @param _l2Token The address of ERC721 NFT in layer 2.
/// @param _from The address of sender in layer 2.
/// @param _to The address of recipient in layer 1.
/// @notice Emitted when the ERC721 NFT is batch transfered to recipient on layer 1.
/// @param _l1Token The address of ERC721 NFT on layer 1.
/// @param _l2Token The address of ERC721 NFT on layer 2.
/// @param _from The address of sender on layer 2.
/// @param _to The address of recipient on layer 1.
/// @param _tokenIds The list of token ids of the ERC721 NFT to withdraw from layer 2.
event FinalizeBatchWithdrawERC721(
address indexed _l1Token,
@@ -36,12 +36,12 @@ interface IL1ERC721Gateway {
uint256[] _tokenIds
);
/// @notice Emitted when the ERC721 NFT is deposited to gateway in layer 1.
/// @param _l1Token The address of ERC721 NFT in layer 1.
/// @param _l2Token The address of ERC721 NFT in layer 2.
/// @param _from The address of sender in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _tokenId The token id of the ERC721 NFT to deposit in layer 1.
/// @notice Emitted when the ERC721 NFT is deposited to gateway on layer 1.
/// @param _l1Token The address of ERC721 NFT on layer 1.
/// @param _l2Token The address of ERC721 NFT on layer 2.
/// @param _from The address of sender on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenId The token id of the ERC721 NFT to deposit on layer 1.
event DepositERC721(
address indexed _l1Token,
address indexed _l2Token,
@@ -50,12 +50,12 @@ interface IL1ERC721Gateway {
uint256 _tokenId
);
/// @notice Emitted when the ERC721 NFT is batch deposited to gateway in layer 1.
/// @param _l1Token The address of ERC721 NFT in layer 1.
/// @param _l2Token The address of ERC721 NFT in layer 2.
/// @param _from The address of sender in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _tokenIds The list of token ids of the ERC721 NFT to deposit in layer 1.
/// @notice Emitted when the ERC721 NFT is batch deposited to gateway on layer 1.
/// @param _l1Token The address of ERC721 NFT on layer 1.
/// @param _l2Token The address of ERC721 NFT on layer 2.
/// @param _from The address of sender on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenIds The list of token ids of the ERC721 NFT to deposit on layer 1.
event BatchDepositERC721(
address indexed _l1Token,
address indexed _l2Token,
@@ -81,7 +81,7 @@ interface IL1ERC721Gateway {
*****************************/
/// @notice Deposit some ERC721 NFT to caller's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
/// @param _token The address of ERC721 NFT on layer 1.
/// @param _tokenId The token id to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
function depositERC721(
@@ -91,8 +91,8 @@ interface IL1ERC721Gateway {
) external payable;
/// @notice Deposit some ERC721 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC721 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenId The token id to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
function depositERC721(
@@ -103,7 +103,7 @@ interface IL1ERC721Gateway {
) external payable;
/// @notice Deposit a list of some ERC721 NFT to caller's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
/// @param _token The address of ERC721 NFT on layer 1.
/// @param _tokenIds The list of token ids to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
function batchDepositERC721(
@@ -113,8 +113,8 @@ interface IL1ERC721Gateway {
) external payable;
/// @notice Deposit a list of some ERC721 NFT to a recipient's account on layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC721 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenIds The list of token ids to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
function batchDepositERC721(
@@ -124,14 +124,14 @@ interface IL1ERC721Gateway {
uint256 _gasLimit
) external payable;
/// @notice Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient's account in layer 1.
/// @notice Complete ERC721 withdraw from layer 2 to layer 1 and send NFT to recipient's account on layer 1.
/// @dev Requirements:
/// - The function should only be called by L1ScrollMessenger.
/// - The function should also only be called by L2ERC721Gateway in layer 2.
/// - The function should also only be called by L2ERC721Gateway on layer 2.
/// @param _l1Token The address of corresponding layer 1 token.
/// @param _l2Token The address of corresponding layer 2 token.
/// @param _from The address of account who withdraw the token in layer 2.
/// @param _to The address of recipient in layer 1 to receive the token.
/// @param _from The address of account who withdraw the token on layer 2.
/// @param _to The address of recipient on layer 1 to receive the token.
/// @param _tokenId The token id to withdraw.
function finalizeWithdrawERC721(
address _l1Token,
@@ -141,14 +141,14 @@ interface IL1ERC721Gateway {
uint256 _tokenId
) external;
/// @notice Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient's account in layer 1.
/// @notice Complete ERC721 batch withdraw from layer 2 to layer 1 and send NFT to recipient's account on layer 1.
/// @dev Requirements:
/// - The function should only be called by L1ScrollMessenger.
/// - The function should also only be called by L2ERC721Gateway in layer 2.
/// - The function should also only be called by L2ERC721Gateway on layer 2.
/// @param _l1Token The address of corresponding layer 1 token.
/// @param _l2Token The address of corresponding layer 2 token.
/// @param _from The address of account who withdraw the token in layer 2.
/// @param _to The address of recipient in layer 1 to receive the token.
/// @param _from The address of account who withdraw the token on layer 2.
/// @param _to The address of recipient on layer 1 to receive the token.
/// @param _tokenIds The list of token ids to withdraw.
function finalizeBatchWithdrawERC721(
address _l1Token,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
interface IL1ETHGateway {
/**********

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
import {IL1ETHGateway} from "./IL1ETHGateway.sol";
import {IL1ERC20Gateway} from "./IL1ERC20Gateway.sol";

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
@@ -14,7 +14,7 @@ import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
import {L1ERC20Gateway} from "./L1ERC20Gateway.sol";
/// @title L1CustomERC20Gateway
/// @notice The `L1CustomERC20Gateway` is used to deposit custom ERC20 compatible tokens in layer 1 and
/// @notice The `L1CustomERC20Gateway` is used to deposit custom ERC20 compatible tokens on layer 1 and
/// 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.
@@ -26,8 +26,8 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
**********/
/// @notice Emitted when token mapping for ERC20 token is updated.
/// @param _l1Token The address of ERC20 token in layer 1.
/// @param _l2Token The address of corresponding ERC20 token in layer 2.
/// @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);
/*************
@@ -41,6 +41,10 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
* Constructor *
***************/
constructor() {
_disableInitializers();
}
/// @notice Initialize the storage of L1CustomERC20Gateway.
/// @param _counterpart The address of L2CustomERC20Gateway in L2.
/// @param _router The address of L1GatewayRouter.
@@ -70,8 +74,8 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
************************/
/// @notice Update layer 1 to layer 2 token mapping.
/// @param _l1Token The address of ERC20 token in layer 1.
/// @param _l2Token The address of corresponding ERC20 token in layer 2.
/// @param _l1Token The address of ERC20 token on layer 1.
/// @param _l2Token The address of corresponding ERC20 token on layer 2.
function updateTokenMapping(address _l1Token, address _l2Token) external onlyOwner {
require(_l2Token != address(0), "token address cannot be 0");
@@ -123,14 +127,9 @@ contract L1CustomERC20Gateway is OwnableUpgradeable, ScrollGatewayBase, L1ERC20G
(_from, _amount, _data) = _transferERC20In(_token, _amount, _data);
// 2. Generate message passed to L2CustomERC20Gateway.
bytes memory _message = abi.encodeWithSelector(
IL2ERC20Gateway.finalizeDepositERC20.selector,
_token,
_l2Token,
_from,
_to,
_amount,
_data
bytes memory _message = abi.encodeCall(
IL2ERC20Gateway.finalizeDepositERC20,
(_token, _l2Token, _from, _to, _amount, _data)
);
// 3. Send message to L1ScrollMessenger.

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC1155Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol";
@@ -14,7 +14,7 @@ import {IMessageDropCallback} from "../../libraries/callbacks/IMessageDropCallba
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// @title L1ERC1155Gateway
/// @notice The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT in layer 1 and
/// @notice The `L1ERC1155Gateway` is used to deposit ERC1155 compatible NFT on layer 1 and
/// finalize withdraw the NFTs from layer 2.
/// @dev The deposited NFTs are held in this gateway. On finalizing withdraw, the corresponding
/// NFT will be transfer to the recipient directly.
@@ -32,8 +32,8 @@ contract L1ERC1155Gateway is
**********/
/// @notice Emitted when token mapping for ERC1155 token is updated.
/// @param _l1Token The address of ERC1155 token in layer 1.
/// @param _l1Token The address of corresponding ERC1155 token in layer 2.
/// @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);
/*************
@@ -47,6 +47,10 @@ contract L1ERC1155Gateway is
* Constructor *
***************/
constructor() {
_disableInitializers();
}
/// @notice Initialize the storage of L1ERC1155Gateway.
/// @param _counterpart The address of L2ERC1155Gateway in L2.
/// @param _messenger The address of L1ScrollMessenger.
@@ -168,8 +172,8 @@ contract L1ERC1155Gateway is
************************/
/// @notice Update layer 2 to layer 2 token mapping.
/// @param _l1Token The address of ERC1155 token in layer 1.
/// @param _l1Token The address of corresponding ERC1155 token in layer 2.
/// @param _l1Token The address of ERC1155 token on layer 1.
/// @param _l2Token The address of corresponding ERC1155 token on layer 2.
function updateTokenMapping(address _l1Token, address _l2Token) external onlyOwner {
require(_l2Token != address(0), "token address cannot be 0");
@@ -183,8 +187,8 @@ contract L1ERC1155Gateway is
**********************/
/// @dev Internal function to deposit ERC1155 NFT to layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC1155 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenId The token id to deposit.
/// @param _amount The amount of token to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
@@ -204,14 +208,9 @@ contract L1ERC1155Gateway is
IERC1155Upgradeable(_token).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// 2. Generate message passed to L2ERC1155Gateway.
bytes memory _message = abi.encodeWithSelector(
IL2ERC1155Gateway.finalizeDepositERC1155.selector,
_token,
_l2Token,
msg.sender,
_to,
_tokenId,
_amount
bytes memory _message = abi.encodeCall(
IL2ERC1155Gateway.finalizeDepositERC1155,
(_token, _l2Token, msg.sender, _to, _tokenId, _amount)
);
// 3. Send message to L1ScrollMessenger.
@@ -221,8 +220,8 @@ contract L1ERC1155Gateway is
}
/// @dev Internal function to batch deposit ERC1155 NFT to layer 2.
/// @param _token The address of ERC1155 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC1155 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenIds The list of token ids to deposit.
/// @param _amounts The list of corresponding number of token to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
@@ -247,14 +246,9 @@ contract L1ERC1155Gateway is
IERC1155Upgradeable(_token).safeBatchTransferFrom(msg.sender, address(this), _tokenIds, _amounts, "");
// 2. Generate message passed to L2ERC1155Gateway.
bytes memory _message = abi.encodeWithSelector(
IL2ERC1155Gateway.finalizeBatchDepositERC1155.selector,
_token,
_l2Token,
msg.sender,
_to,
_tokenIds,
_amounts
bytes memory _message = abi.encodeCall(
IL2ERC1155Gateway.finalizeBatchDepositERC1155,
(_token, _l2Token, msg.sender, _to, _tokenIds, _amounts)
);
// 3. Send message to L1ScrollMessenger.

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.16;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
@@ -21,6 +21,13 @@ import {IMessageDropCallback} from "../../libraries/callbacks/IMessageDropCallba
abstract contract L1ERC20Gateway is IL1ERC20Gateway, IMessageDropCallback, ScrollGatewayBase {
using SafeERC20 for IERC20;
/*************
* Variables *
*************/
/// @dev The storage slots for future usage.
uint256[50] private __gap;
/*****************************
* Public Mutating Functions *
*****************************/

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity =0.8.16;
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
@@ -14,7 +14,7 @@ import {IMessageDropCallback} from "../../libraries/callbacks/IMessageDropCallba
import {ScrollGatewayBase} from "../../libraries/gateway/ScrollGatewayBase.sol";
/// @title L1ERC721Gateway
/// @notice The `L1ERC721Gateway` is used to deposit ERC721 compatible NFT in layer 1 and
/// @notice The `L1ERC721Gateway` is used to deposit ERC721 compatible NFT on layer 1 and
/// finalize withdraw the NFTs from layer 2.
/// @dev The deposited NFTs are held in this gateway. On finalizing withdraw, the corresponding
/// NFT will be transfer to the recipient directly.
@@ -32,8 +32,8 @@ contract L1ERC721Gateway is
**********/
/// @notice Emitted when token mapping for ERC721 token is updated.
/// @param _l1Token The address of ERC721 token in layer 1.
/// @param _l1Token The address of corresponding ERC721 token in layer 2.
/// @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);
/*************
@@ -47,6 +47,10 @@ contract L1ERC721Gateway is
* Constructor *
***************/
constructor() {
_disableInitializers();
}
/// @notice Initialize the storage of L1ERC721Gateway.
/// @param _counterpart The address of L2ERC721Gateway in L2.
/// @param _messenger The address of L1ScrollMessenger.
@@ -164,8 +168,8 @@ contract L1ERC721Gateway is
************************/
/// @notice Update layer 2 to layer 2 token mapping.
/// @param _l1Token The address of ERC721 token in layer 1.
/// @param _l1Token The address of corresponding ERC721 token in layer 2.
/// @param _l1Token The address of ERC721 token on layer 1.
/// @param _l2Token The address of corresponding ERC721 token on layer 2.
function updateTokenMapping(address _l1Token, address _l2Token) external onlyOwner {
require(_l2Token != address(0), "token address cannot be 0");
@@ -179,8 +183,8 @@ contract L1ERC721Gateway is
**********************/
/// @dev Internal function to deposit ERC721 NFT to layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC721 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenId The token id to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
function _depositERC721(
@@ -196,13 +200,9 @@ contract L1ERC721Gateway is
IERC721Upgradeable(_token).safeTransferFrom(msg.sender, address(this), _tokenId);
// 2. Generate message passed to L2ERC721Gateway.
bytes memory _message = abi.encodeWithSelector(
IL2ERC721Gateway.finalizeDepositERC721.selector,
_token,
_l2Token,
msg.sender,
_to,
_tokenId
bytes memory _message = abi.encodeCall(
IL2ERC721Gateway.finalizeDepositERC721,
(_token, _l2Token, msg.sender, _to, _tokenId)
);
// 3. Send message to L1ScrollMessenger.
@@ -212,8 +212,8 @@ contract L1ERC721Gateway is
}
/// @dev Internal function to batch deposit ERC721 NFT to layer 2.
/// @param _token The address of ERC721 NFT in layer 1.
/// @param _to The address of recipient in layer 2.
/// @param _token The address of ERC721 NFT on layer 1.
/// @param _to The address of recipient on layer 2.
/// @param _tokenIds The list of token ids to deposit.
/// @param _gasLimit Estimated gas limit required to complete the deposit on layer 2.
function _batchDepositERC721(
@@ -233,13 +233,9 @@ contract L1ERC721Gateway is
}
// 2. Generate message passed to L2ERC721Gateway.
bytes memory _message = abi.encodeWithSelector(
IL2ERC721Gateway.finalizeBatchDepositERC721.selector,
_token,
_l2Token,
msg.sender,
_to,
_tokenIds
bytes memory _message = abi.encodeCall(
IL2ERC721Gateway.finalizeBatchDepositERC721,
(_token, _l2Token, msg.sender, _to, _tokenIds)
);
// 3. Send message to L1ScrollMessenger.

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