arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/synchronizer/synchronizer.go
synchronizer/synchronizer.goRaw
  1package synchronizer
  2
  3import (
  4	"context"
  5	"database/sql"
  6	"fmt"
  7	"math/big"
  8
  9	"github.com/ethereum/go-ethereum"
 10	"github.com/hermeznetwork/hermez-node/common"
 11	"github.com/hermeznetwork/hermez-node/db/historydb"
 12	"github.com/hermeznetwork/hermez-node/db/statedb"
 13	"github.com/hermeznetwork/hermez-node/eth"
 14	"github.com/hermeznetwork/hermez-node/log"
 15)
 16
 17var (
 18// ErrNotAbleToSync is used when there is not possible to find a valid block to sync
 19// ErrNotAbleToSync = errors.New("it has not been possible to synchronize any block")
 20)
 21
 22// // SyncronizerState describes the synchronization progress of the smart contracts
 23// type SyncronizerState struct {
 24// 	LastUpdate                time.Time // last time this information was updated
 25// 	CurrentBatchNum           BatchNum  // Last batch that was forged on the blockchain
 26// 	CurrentBlockNum           uint64    // Last block that was mined on Ethereum
 27// 	CurrentToForgeL1TxsNum    uint32
 28// 	LastSyncedBatchNum        BatchNum // last batch synchronized by the coordinator
 29// 	LastSyncedBlockNum        uint64   // last Ethereum block synchronized by the coordinator
 30// 	LastSyncedToForgeL1TxsNum uint32
 31// }
 32
 33// // SyncStatus is returned by the Status method of the Synchronizer
 34// type SyncStatus struct {
 35// 	CurrentBlock      int64
 36// 	CurrentBatch      BatchNum
 37// 	CurrentForgerAddr ethCommon.Address
 38// 	NextForgerAddr    ethCommon.Address
 39// 	Synchronized      bool
 40// }
 41
 42// ConfigStartBlockNum sets the first block used to start tracking the smart
 43// contracts
 44type ConfigStartBlockNum struct {
 45	Rollup   int64 `validate:"required"`
 46	Auction  int64 `validate:"required"`
 47	WDelayer int64 `validate:"required"`
 48}
 49
 50// SCVariables joins all the smart contract variables in a single struct
 51type SCVariables struct {
 52	Rollup   common.RollupVariables   `validate:"required"`
 53	Auction  common.AuctionVariables  `validate:"required"`
 54	WDelayer common.WDelayerVariables `validate:"required"`
 55}
 56
 57// Config is the Synchronizer configuration
 58type Config struct {
 59	StartBlockNum    ConfigStartBlockNum
 60	InitialVariables SCVariables
 61}
 62
 63// Synchronizer implements the Synchronizer type
 64type Synchronizer struct {
 65	ethClient         eth.ClientInterface
 66	auctionConstants  common.AuctionConstants
 67	rollupConstants   common.RollupConstants
 68	wDelayerConstants common.WDelayerConstants
 69	historyDB         *historydb.HistoryDB
 70	stateDB           *statedb.StateDB
 71	cfg               Config
 72	startBlockNum     int64
 73	vars              SCVariables
 74	// firstSavedBlock  *common.Block
 75	// mux sync.Mutex
 76}
 77
 78// NewSynchronizer creates a new Synchronizer
 79func NewSynchronizer(ethClient eth.ClientInterface, historyDB *historydb.HistoryDB,
 80	stateDB *statedb.StateDB, cfg Config) (*Synchronizer, error) {
 81	auctionConstants, err := ethClient.AuctionConstants()
 82	if err != nil {
 83		log.Errorw("NewSynchronizer ethClient.AuctionConstants()", "err", err)
 84		return nil, err
 85	}
 86	rollupConstants, err := ethClient.RollupConstants()
 87	if err != nil {
 88		log.Errorw("NewSynchronizer ethClient.RollupConstants()", "err", err)
 89		return nil, err
 90	}
 91	wDelayerConstants, err := ethClient.WDelayerConstants()
 92	if err != nil {
 93		log.Errorw("NewSynchronizer ethClient.WDelayerConstants()", "err", err)
 94		return nil, err
 95	}
 96
 97	// Set startBlockNum to the minimum between Auction, Rollup and
 98	// WDelayer StartBlockNum
 99	startBlockNum := cfg.StartBlockNum.Auction
100	if startBlockNum < cfg.StartBlockNum.Rollup {
101		startBlockNum = cfg.StartBlockNum.Rollup
102	}
103	if startBlockNum < cfg.StartBlockNum.WDelayer {
104		startBlockNum = cfg.StartBlockNum.WDelayer
105	}
106	s := &Synchronizer{
107		ethClient:         ethClient,
108		auctionConstants:  *auctionConstants,
109		rollupConstants:   *rollupConstants,
110		wDelayerConstants: *wDelayerConstants,
111		historyDB:         historyDB,
112		stateDB:           stateDB,
113		cfg:               cfg,
114		startBlockNum:     startBlockNum,
115	}
116	return s, s.init()
117}
118
119// AuctionConstants returns the AuctionConstants read from the smart contract
120func (s *Synchronizer) AuctionConstants() *common.AuctionConstants {
121	return &s.auctionConstants
122}
123
124// RollupConstants returns the RollupConstants read from the smart contract
125func (s *Synchronizer) RollupConstants() *common.RollupConstants {
126	return &s.rollupConstants
127}
128
129// WDelayerConstants returns the WDelayerConstants read from the smart contract
130func (s *Synchronizer) WDelayerConstants() *common.WDelayerConstants {
131	return &s.wDelayerConstants
132}
133
134func (s *Synchronizer) init() error {
135	rollup, auction, wDelayer, err := s.historyDB.GetSCVars()
136	if err == sql.ErrNoRows {
137		rollup = &s.cfg.InitialVariables.Rollup
138		auction = &s.cfg.InitialVariables.Auction
139		wDelayer = &s.cfg.InitialVariables.WDelayer
140		log.Debug("Setting initial SCVars in HistoryDB")
141		if err = s.historyDB.SetInitialSCVars(rollup, auction, wDelayer); err != nil {
142			return err
143		}
144	}
145	s.vars.Rollup = *rollup
146	s.vars.Auction = *auction
147	s.vars.WDelayer = *wDelayer
148	return nil
149}
150
151// Sync2 attems to synchronize an ethereum block starting from lastSavedBlock.
152// If lastSavedBlock is nil, the lastSavedBlock value is obtained from de DB.
153// If a block is synched, it will be returned and also stored in the DB.  If a
154// reorg is detected, the number of discarded blocks will be returned and no
155// synchronization will be made.
156// TODO: Be smart about locking: only lock during the read/write operations
157func (s *Synchronizer) Sync2(ctx context.Context, lastSavedBlock *common.Block) (*common.BlockData, *int64, error) {
158	var nextBlockNum int64 // next block number to sync
159	if lastSavedBlock == nil {
160		var err error
161		// Get lastSavedBlock from History DB
162		lastSavedBlock, err = s.historyDB.GetLastBlock()
163		if err != nil && err != sql.ErrNoRows {
164			return nil, nil, err
165		}
166		// If we don't have any stored block, we must do a full sync
167		// starting from the startBlockNum
168		if err == sql.ErrNoRows || lastSavedBlock.EthBlockNum == 0 {
169			nextBlockNum = s.startBlockNum
170			lastSavedBlock = nil
171		}
172	}
173	if lastSavedBlock != nil {
174		nextBlockNum = lastSavedBlock.EthBlockNum + 1
175	}
176
177	ethBlock, err := s.ethClient.EthBlockByNumber(ctx, nextBlockNum)
178	if err == ethereum.NotFound {
179		return nil, nil, nil
180	} else if err != nil {
181		return nil, nil, err
182	}
183	log.Debugf("ethBlock: num: %v, parent: %v, hash: %v", ethBlock.EthBlockNum, ethBlock.ParentHash.String(), ethBlock.Hash.String())
184
185	log.Debugw("Syncing...", "block", nextBlockNum)
186
187	// Check that the obtianed ethBlock.ParentHash == prevEthBlock.Hash; if not, reorg!
188	if lastSavedBlock != nil {
189		if lastSavedBlock.Hash != ethBlock.ParentHash {
190			// Reorg detected
191			log.Debugw("Reorg Detected",
192				"blockNum", ethBlock.EthBlockNum,
193				"block.parent(got)", ethBlock.ParentHash, "parent.hash(exp)", lastSavedBlock.Hash)
194			lastDBBlockNum, err := s.reorg(lastSavedBlock)
195			if err != nil {
196				return nil, nil, err
197			}
198			discarded := lastSavedBlock.EthBlockNum - lastDBBlockNum
199			return nil, &discarded, nil
200		}
201	}
202
203	// Get data from the rollup contract
204	rollupData, err := s.rollupSync(ethBlock)
205	if err != nil {
206		return nil, nil, err
207	}
208
209	// Get data from the auction contract
210	auctionData, err := s.auctionSync(ethBlock)
211	if err != nil {
212		return nil, nil, err
213	}
214
215	// Get data from the WithdrawalDelayer contract
216	wDelayerData, err := s.wdelayerSync(ethBlock)
217	if err != nil {
218		return nil, nil, err
219	}
220
221	for i := range rollupData.Withdrawals {
222		withdrawal := &rollupData.Withdrawals[i]
223		if !withdrawal.InstantWithdraw {
224			wDelayerTransfer, ok := wDelayerData.DepositsByTxHash[withdrawal.TxHash]
225			if !ok {
226				return nil, nil, fmt.Errorf("WDelayer deposit corresponding to " +
227					"non-instant rollup withdrawal not found")
228			}
229			withdrawal.Owner = wDelayerTransfer.Owner
230			withdrawal.Token = wDelayerTransfer.Token
231		}
232	}
233
234	// Group all the block data into the structs to save into HistoryDB
235	blockData := common.BlockData{
236		Block:    *ethBlock,
237		Rollup:   *rollupData,
238		Auction:  *auctionData,
239		WDelayer: *wDelayerData,
240	}
241
242	// log.Debugw("Sync()", "block", blockData)
243	// err = s.historyDB.AddBlock(blockData.Block)
244	// if err != nil {
245	// 	return err
246	// }
247	err = s.historyDB.AddBlockSCData(&blockData)
248	if err != nil {
249		return nil, nil, err
250	}
251
252	return &blockData, nil, nil
253}
254
255// reorg manages a reorg, updating History and State DB as needed.  Keeps
256// checking previous blocks from the HistoryDB against the blockchain until a
257// block hash match is found.  All future blocks in the HistoryDB and
258// corresponding batches in StateBD are discarded.  Returns the last valid
259// blockNum from the HistoryDB.
260func (s *Synchronizer) reorg(uncleBlock *common.Block) (int64, error) {
261	blockNum := uncleBlock.EthBlockNum
262
263	for blockNum >= s.startBlockNum {
264		ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), blockNum)
265		if err != nil {
266			return 0, err
267		}
268
269		block, err := s.historyDB.GetBlock(blockNum)
270		if err != nil {
271			return 0, err
272		}
273		if block.Hash == ethBlock.Hash {
274			log.Debugf("Found valid block: %v", blockNum)
275			break
276		}
277		blockNum--
278	}
279	total := uncleBlock.EthBlockNum - blockNum
280	log.Debugw("Discarding blocks", "total", total, "from", uncleBlock.EthBlockNum, "to", blockNum+1)
281
282	// Set History DB and State DB to the correct state
283	err := s.historyDB.Reorg(blockNum)
284	if err != nil {
285		return 0, err
286	}
287
288	batchNum, err := s.historyDB.GetLastBatchNum()
289	if err != nil && err != sql.ErrNoRows {
290		return 0, err
291	}
292	if err == sql.ErrNoRows {
293		batchNum = 0
294	}
295	err = s.stateDB.Reset(batchNum)
296	if err != nil {
297		return 0, err
298	}
299
300	return blockNum, nil
301}
302
303// TODO: Figure out who will use the Status output, and only return what's strictly need
304/*
305// Status returns current status values from the Synchronizer
306func (s *Synchronizer) Status() (*common.SyncStatus, error) {
307	// Avoid possible inconsistencies
308	s.mux.Lock()
309	defer s.mux.Unlock()
310
311	var status *common.SyncStatus
312
313	// TODO: Join all queries to the DB into a single transaction so that
314	// we can remove the mutex locking here:
315	// - HistoryDB.GetLastBlock
316	// - HistoryDB.GetLastBatchNum
317	// - HistoryDB.GetCurrentForgerAddr
318	// - HistoryDB.GetNextForgerAddr
319
320	// Get latest block in History DB
321	lastSavedBlock, err := s.historyDB.GetLastBlock()
322	if err != nil {
323		return nil, err
324	}
325	status.CurrentBlock = lastSavedBlock.EthBlockNum
326
327	// Get latest batch in History DB
328	lastSavedBatch, err := s.historyDB.GetLastBatchNum()
329	if err != nil && err != sql.ErrNoRows {
330		return nil, err
331	}
332	status.CurrentBatch = lastSavedBatch
333
334	// Get latest blockNum in blockchain
335	latestBlockNum, err := s.ethClient.EthCurrentBlock()
336	if err != nil {
337		return nil, err
338	}
339
340	// TODO: Get CurrentForgerAddr & NextForgerAddr from the Auction SC / Or from the HistoryDB
341
342	// Check if Synchronizer is synchronized
343	status.Synchronized = status.CurrentBlock == latestBlockNum
344	return status, nil
345}
346*/
347
348// rollupSync retreives all the Rollup Smart Contract Data that happened at
349// ethBlock.blockNum with ethBlock.Hash.
350func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, error) {
351	blockNum := ethBlock.EthBlockNum
352	var rollupData = common.NewRollupData()
353	// var forgeL1TxsNum int64
354
355	// Get rollup events in the block, and make sure the block hash matches
356	// the expected one.
357	rollupEvents, blockHash, err := s.ethClient.RollupEventsByBlock(blockNum)
358	if err != nil {
359		return nil, err
360	}
361	// No events in this block
362	if blockHash == nil {
363		return &rollupData, nil
364	}
365	if *blockHash != ethBlock.Hash {
366		log.Errorw("Block hash mismatch in Rollup events", "expected", ethBlock.Hash.String(),
367			"got", blockHash.String())
368		return nil, eth.ErrBlockHashMismatchEvent
369	}
370
371	var nextForgeL1TxsNum int64 // forgeL1TxsNum for the next L1Batch
372	nextForgeL1TxsNumPtr, err := s.historyDB.GetLastL1TxsNum()
373	if err != nil {
374		return nil, err
375	}
376	if nextForgeL1TxsNumPtr != nil {
377		nextForgeL1TxsNum = *nextForgeL1TxsNumPtr + 1
378	} else {
379		nextForgeL1TxsNum = 0
380	}
381
382	// Get L1UserTX
383	rollupData.L1UserTxs, err = getL1UserTx(rollupEvents.L1UserTx, blockNum)
384	if err != nil {
385		return nil, err
386	}
387
388	// Get ForgeBatch events to get the L1CoordinatorTxs
389	for _, evtForgeBatch := range rollupEvents.ForgeBatch {
390		batchData := common.NewBatchData()
391		position := 0
392
393		// Get the input for each Tx
394		forgeBatchArgs, sender, err := s.ethClient.RollupForgeBatchArgs(evtForgeBatch.EthTxHash)
395		if err != nil {
396			return nil, err
397		}
398
399		batchNum := common.BatchNum(evtForgeBatch.BatchNum)
400		var l1UserTxs []common.L1Tx
401		// Check if this is a L1Batch to get L1 Tx from it
402		if forgeBatchArgs.L1Batch {
403			// Get L1UserTxs with toForgeL1TxsNum, which correspond
404			// to the L1UserTxs that are forged in this batch, so
405			// that stateDB can process them.
406
407			// First try to find them in HistoryDB.
408			l1UserTxs, err = s.historyDB.GetL1UserTxs(nextForgeL1TxsNum)
409			if err != nil {
410				return nil, err
411			}
412			// Apart from the DB, try to find them in this block.
413			// This could happen because in a block there could be
414			// multiple batches with L1Batch = true (although it's
415			// a very rare case).  If not found in the DB and the
416			// block doesn't contain the l1UserTxs, it means that
417			// the L1UserTxs queue with toForgeL1TxsNum was closed
418			// empty, so we leave `l1UserTxs` as an empty slice.
419			for _, l1UserTx := range rollupData.L1UserTxs {
420				if *l1UserTx.ToForgeL1TxsNum == nextForgeL1TxsNum {
421					l1UserTxs = append(l1UserTxs, l1UserTx)
422				}
423			}
424
425			position = len(l1UserTxs)
426		}
427		// Get L1 Coordinator Txs
428		for i := range forgeBatchArgs.L1CoordinatorTxs {
429			l1CoordinatorTx := forgeBatchArgs.L1CoordinatorTxs[i]
430			l1CoordinatorTx.Position = position
431			// l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum
432			l1CoordinatorTx.UserOrigin = false
433			l1CoordinatorTx.EthBlockNum = blockNum
434			l1CoordinatorTx.BatchNum = &batchNum
435			l1Tx, err := common.NewL1Tx(&l1CoordinatorTx)
436			if err != nil {
437				return nil, err
438			}
439
440			batchData.L1CoordinatorTxs = append(batchData.L1CoordinatorTxs, *l1Tx)
441			position++
442			// fmt.Println("DGB l1coordtx")
443		}
444
445		// Insert all the txs forged in this batch (l1UserTxs,
446		// L1CoordinatorTxs, PoolL2Txs) into stateDB so that they are
447		// processed.
448		poolL2Txs := common.L2TxsToPoolL2Txs(forgeBatchArgs.L2TxsData) // NOTE: This is a big ugly, find a better way
449
450		// ProcessTxs updates poolL2Txs adding: Nonce (and also TokenID, but we don't use it).
451		processTxsOut, err := s.stateDB.ProcessTxs(forgeBatchArgs.FeeIdxCoordinator, l1UserTxs,
452			batchData.L1CoordinatorTxs, poolL2Txs)
453		if err != nil {
454			return nil, err
455		}
456
457		// Set batchNum in exits
458		for i := range processTxsOut.ExitInfos {
459			exit := &processTxsOut.ExitInfos[i]
460			exit.BatchNum = batchNum
461		}
462		batchData.ExitTree = processTxsOut.ExitInfos
463
464		l2Txs, err := common.PoolL2TxsToL2Txs(poolL2Txs) // NOTE: This is a big uggly, find a better way
465		if err != nil {
466			return nil, err
467		}
468
469		for i := range l2Txs {
470			tx := &l2Txs[i]
471			tx.Position = position
472			tx.EthBlockNum = blockNum
473			tx.BatchNum = batchNum
474			nTx, err := common.NewL2Tx(tx)
475			if err != nil {
476				return nil, err
477			}
478
479			batchData.L2Txs = append(batchData.L2Txs, *nTx)
480			position++
481		}
482
483		for i := range processTxsOut.CreatedAccounts {
484			createdAccount := &processTxsOut.CreatedAccounts[i]
485			createdAccount.Nonce = 0
486			createdAccount.Balance = big.NewInt(0)
487			createdAccount.BatchNum = batchNum
488		}
489		batchData.CreatedAccounts = processTxsOut.CreatedAccounts
490
491		slotNum := int64(0)
492		if ethBlock.EthBlockNum >= s.auctionConstants.GenesisBlockNum {
493			slotNum = (ethBlock.EthBlockNum - s.auctionConstants.GenesisBlockNum) /
494				int64(s.auctionConstants.BlocksPerSlot)
495		}
496
497		// Get Batch information
498		batch := common.Batch{
499			BatchNum:           batchNum,
500			EthBlockNum:        blockNum,
501			ForgerAddr:         *sender,
502			CollectedFees:      processTxsOut.CollectedFees,
503			FeeIdxsCoordinator: forgeBatchArgs.FeeIdxCoordinator,
504			StateRoot:          forgeBatchArgs.NewStRoot,
505			NumAccounts:        len(batchData.CreatedAccounts),
506			LastIdx:            forgeBatchArgs.NewLastIdx,
507			ExitRoot:           forgeBatchArgs.NewExitRoot,
508			SlotNum:            slotNum,
509		}
510		nextForgeL1TxsNumCpy := nextForgeL1TxsNum
511		if forgeBatchArgs.L1Batch {
512			batch.ForgeL1TxsNum = &nextForgeL1TxsNumCpy
513			batchData.L1Batch = true
514			nextForgeL1TxsNum++
515		}
516		batchData.Batch = batch
517		rollupData.Batches = append(rollupData.Batches, *batchData)
518	}
519
520	// Get Registered Tokens
521	for _, evtAddToken := range rollupEvents.AddToken {
522		var token common.Token
523
524		token.TokenID = common.TokenID(evtAddToken.TokenID)
525		token.EthAddr = evtAddToken.TokenAddress
526		token.EthBlockNum = blockNum
527
528		if consts, err := s.ethClient.EthERC20Consts(evtAddToken.TokenAddress); err != nil {
529			log.Warnw("Error retreiving ERC20 token constants", "addr", evtAddToken.TokenAddress)
530			token.Name = "ERC20_ETH_ERROR"
531			token.Symbol = "ERROR"
532			token.Decimals = 1
533		} else {
534			token.Name = cutStringMax(consts.Name, 20)
535			token.Symbol = cutStringMax(consts.Symbol, 10)
536			token.Decimals = consts.Decimals
537		}
538
539		rollupData.AddedTokens = append(rollupData.AddedTokens, token)
540	}
541
542	varsUpdate := false
543
544	for _, evtUpdateForgeL1L2BatchTimeout := range rollupEvents.UpdateForgeL1L2BatchTimeout {
545		s.vars.Rollup.ForgeL1L2BatchTimeout = evtUpdateForgeL1L2BatchTimeout.NewForgeL1L2BatchTimeout
546		varsUpdate = true
547	}
548
549	for _, evtUpdateFeeAddToken := range rollupEvents.UpdateFeeAddToken {
550		s.vars.Rollup.FeeAddToken = evtUpdateFeeAddToken.NewFeeAddToken
551		varsUpdate = true
552	}
553
554	// NOTE: WithdrawDelay update doesn't have event, so we can't track changes
555
556	// NOTE: Buckets update dones't have event, so we can't track changes
557
558	for _, evtWithdraw := range rollupEvents.Withdraw {
559		rollupData.Withdrawals = append(rollupData.Withdrawals, common.WithdrawInfo{
560			Idx:             common.Idx(evtWithdraw.Idx),
561			NumExitRoot:     common.BatchNum(evtWithdraw.NumExitRoot),
562			InstantWithdraw: evtWithdraw.InstantWithdraw,
563			TxHash:          evtWithdraw.TxHash,
564		})
565	}
566
567	if varsUpdate {
568		s.vars.Rollup.EthBlockNum = blockNum
569		rollupData.Vars = &s.vars.Rollup
570	}
571
572	return &rollupData, nil
573}
574
575func cutStringMax(s string, max int) string {
576	if len(s) > max {
577		return s[:max]
578	}
579	return s
580}
581
582// auctionSync gets information from the Auction Contract
583func (s *Synchronizer) auctionSync(ethBlock *common.Block) (*common.AuctionData, error) {
584	blockNum := ethBlock.EthBlockNum
585	var auctionData = common.NewAuctionData()
586
587	// Get auction events in the block
588	auctionEvents, blockHash, err := s.ethClient.AuctionEventsByBlock(blockNum)
589	if err != nil {
590		return nil, err
591	}
592	// No events in this block
593	if blockHash == nil {
594		return &auctionData, nil
595	}
596	if *blockHash != ethBlock.Hash {
597		log.Errorw("Block hash mismatch in Auction events", "expected", ethBlock.Hash.String(),
598			"got", blockHash.String())
599		return nil, eth.ErrBlockHashMismatchEvent
600	}
601
602	// Get bids
603	for _, evtNewBid := range auctionEvents.NewBid {
604		bid := common.Bid{
605			SlotNum:     evtNewBid.Slot,
606			BidValue:    evtNewBid.BidAmount,
607			Bidder:      evtNewBid.Bidder,
608			EthBlockNum: blockNum,
609		}
610		auctionData.Bids = append(auctionData.Bids, bid)
611	}
612
613	// Get Coordinators
614	for _, evtSetCoordinator := range auctionEvents.SetCoordinator {
615		coordinator := common.Coordinator{
616			Bidder: evtSetCoordinator.BidderAddress,
617			Forger: evtSetCoordinator.ForgerAddress,
618			URL:    evtSetCoordinator.CoordinatorURL,
619		}
620		auctionData.Coordinators = append(auctionData.Coordinators, coordinator)
621	}
622
623	varsUpdate := false
624
625	for _, evt := range auctionEvents.NewSlotDeadline {
626		s.vars.Auction.SlotDeadline = evt.NewSlotDeadline
627		varsUpdate = true
628	}
629	for _, evt := range auctionEvents.NewClosedAuctionSlots {
630		s.vars.Auction.ClosedAuctionSlots = evt.NewClosedAuctionSlots
631		varsUpdate = true
632	}
633	for _, evt := range auctionEvents.NewOutbidding {
634		s.vars.Auction.Outbidding = evt.NewOutbidding
635		varsUpdate = true
636	}
637	for _, evt := range auctionEvents.NewDonationAddress {
638		s.vars.Auction.DonationAddress = evt.NewDonationAddress
639		varsUpdate = true
640	}
641	for _, evt := range auctionEvents.NewBootCoordinator {
642		s.vars.Auction.BootCoordinator = evt.NewBootCoordinator
643		varsUpdate = true
644	}
645	for _, evt := range auctionEvents.NewOpenAuctionSlots {
646		s.vars.Auction.OpenAuctionSlots = evt.NewOpenAuctionSlots
647		varsUpdate = true
648	}
649	for _, evt := range auctionEvents.NewAllocationRatio {
650		s.vars.Auction.AllocationRatio = evt.NewAllocationRatio
651		varsUpdate = true
652	}
653	for _, evt := range auctionEvents.NewDefaultSlotSetBid {
654		if evt.SlotSet > 6 { //nolint:gomnd
655			return nil, fmt.Errorf("unexpected SlotSet in "+
656				"auctionEvents.NewDefaultSlotSetBid: %v", evt.SlotSet)
657		}
658		s.vars.Auction.DefaultSlotSetBid[evt.SlotSet] = evt.NewInitialMinBid
659		varsUpdate = true
660	}
661
662	// NOTE: We ignore NewForgeAllocated
663	// NOTE: We ignore NewForge because we're already tracking ForgeBatch event from Rollup
664	// NOTE: We ignore HEZClaimed
665
666	if varsUpdate {
667		s.vars.Auction.EthBlockNum = blockNum
668		auctionData.Vars = &s.vars.Auction
669	}
670
671	return &auctionData, nil
672}
673
674// wdelayerSync gets information from the Withdrawal Delayer Contract
675func (s *Synchronizer) wdelayerSync(ethBlock *common.Block) (*common.WDelayerData, error) {
676	blockNum := ethBlock.EthBlockNum
677	wDelayerData := common.NewWDelayerData()
678
679	// Get wDelayer events in the block
680	wDelayerEvents, blockHash, err := s.ethClient.WDelayerEventsByBlock(blockNum)
681	if err != nil {
682		return nil, err
683	}
684	// No events in this block
685	if blockHash == nil {
686		return &wDelayerData, nil
687	}
688	if *blockHash != ethBlock.Hash {
689		log.Errorw("Block hash mismatch in WDelayer events", "expected", ethBlock.Hash.String(),
690			"got", blockHash.String())
691		return nil, eth.ErrBlockHashMismatchEvent
692	}
693
694	for _, evt := range wDelayerEvents.Deposit {
695		wDelayerData.Deposits = append(wDelayerData.Deposits, common.WDelayerTransfer{
696			Owner:  evt.Owner,
697			Token:  evt.Token,
698			Amount: evt.Amount,
699		})
700		wDelayerData.DepositsByTxHash[evt.TxHash] =
701			&wDelayerData.Deposits[len(wDelayerData.Deposits)-1]
702	}
703	for _, evt := range wDelayerEvents.Withdraw {
704		wDelayerData.Withdrawals = append(wDelayerData.Withdrawals, common.WDelayerTransfer{
705			Owner:  evt.Owner,
706			Token:  evt.Token,
707			Amount: evt.Amount,
708		})
709	}
710
711	varsUpdate := false
712
713	// TODO EscapeHatchWithdrawal
714	for range wDelayerEvents.EmergencyModeEnabled {
715		s.vars.WDelayer.EmergencyMode = true
716		varsUpdate = true
717	}
718	for _, evt := range wDelayerEvents.NewWithdrawalDelay {
719		s.vars.WDelayer.WithdrawalDelay = evt.WithdrawalDelay
720		varsUpdate = true
721	}
722	for _, evt := range wDelayerEvents.NewHermezKeeperAddress {
723		s.vars.WDelayer.HermezKeeperAddress = evt.NewHermezKeeperAddress
724		varsUpdate = true
725	}
726	for _, evt := range wDelayerEvents.NewWhiteHackGroupAddress {
727		s.vars.WDelayer.WhiteHackGroupAddress = evt.NewWhiteHackGroupAddress
728		varsUpdate = true
729	}
730	for _, evt := range wDelayerEvents.NewHermezGovernanceDAOAddress {
731		s.vars.WDelayer.HermezGovernanceDAOAddress = evt.NewHermezGovernanceDAOAddress
732		varsUpdate = true
733	}
734
735	if varsUpdate {
736		s.vars.WDelayer.EthBlockNum = blockNum
737		wDelayerData.Vars = &s.vars.WDelayer
738	}
739
740	return &wDelayerData, nil
741}
742
743func getL1UserTx(eventsL1UserTx []eth.RollupEventL1UserTx, blockNum int64) ([]common.L1Tx, error) {
744	l1Txs := make([]common.L1Tx, len(eventsL1UserTx))
745	for i := range eventsL1UserTx {
746		eventsL1UserTx[i].L1UserTx.EthBlockNum = blockNum
747		// Check validity of L1UserTx
748		l1Tx, err := common.NewL1Tx(&eventsL1UserTx[i].L1UserTx)
749		if err != nil {
750			return nil, err
751		}
752		l1Txs[i] = *l1Tx
753	}
754	return l1Txs, nil
755}