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	// Group all the block data into the structs to save into HistoryDB
222	blockData := common.BlockData{
223		Block:    *ethBlock,
224		Rollup:   *rollupData,
225		Auction:  *auctionData,
226		WDelayer: *wdelayerData,
227	}
228
229	// log.Debugw("Sync()", "block", blockData)
230	// err = s.historyDB.AddBlock(blockData.Block)
231	// if err != nil {
232	// 	return err
233	// }
234	err = s.historyDB.AddBlockSCData(&blockData)
235	if err != nil {
236		return nil, nil, err
237	}
238
239	return &blockData, nil, nil
240}
241
242// reorg manages a reorg, updating History and State DB as needed.  Keeps
243// checking previous blocks from the HistoryDB against the blockchain until a
244// block hash match is found.  All future blocks in the HistoryDB and
245// corresponding batches in StateBD are discarded.  Returns the last valid
246// blockNum from the HistoryDB.
247func (s *Synchronizer) reorg(uncleBlock *common.Block) (int64, error) {
248	blockNum := uncleBlock.EthBlockNum
249
250	for blockNum >= s.startBlockNum {
251		ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), blockNum)
252		if err != nil {
253			return 0, err
254		}
255
256		block, err := s.historyDB.GetBlock(blockNum)
257		if err != nil {
258			return 0, err
259		}
260		if block.Hash == ethBlock.Hash {
261			log.Debugf("Found valid block: %v", blockNum)
262			break
263		}
264		blockNum--
265	}
266	total := uncleBlock.EthBlockNum - blockNum
267	log.Debugw("Discarding blocks", "total", total, "from", uncleBlock.EthBlockNum, "to", blockNum+1)
268
269	// Set History DB and State DB to the correct state
270	err := s.historyDB.Reorg(blockNum)
271	if err != nil {
272		return 0, err
273	}
274
275	batchNum, err := s.historyDB.GetLastBatchNum()
276	if err != nil && err != sql.ErrNoRows {
277		return 0, err
278	}
279	if batchNum != 0 {
280		err = s.stateDB.Reset(batchNum)
281		if err != nil {
282			return 0, err
283		}
284	}
285
286	return blockNum, nil
287}
288
289// TODO: Figure out who will use the Status output, and only return what's strictly need
290/*
291// Status returns current status values from the Synchronizer
292func (s *Synchronizer) Status() (*common.SyncStatus, error) {
293	// Avoid possible inconsistencies
294	s.mux.Lock()
295	defer s.mux.Unlock()
296
297	var status *common.SyncStatus
298
299	// TODO: Join all queries to the DB into a single transaction so that
300	// we can remove the mutex locking here:
301	// - HistoryDB.GetLastBlock
302	// - HistoryDB.GetLastBatchNum
303	// - HistoryDB.GetCurrentForgerAddr
304	// - HistoryDB.GetNextForgerAddr
305
306	// Get latest block in History DB
307	lastSavedBlock, err := s.historyDB.GetLastBlock()
308	if err != nil {
309		return nil, err
310	}
311	status.CurrentBlock = lastSavedBlock.EthBlockNum
312
313	// Get latest batch in History DB
314	lastSavedBatch, err := s.historyDB.GetLastBatchNum()
315	if err != nil && err != sql.ErrNoRows {
316		return nil, err
317	}
318	status.CurrentBatch = lastSavedBatch
319
320	// Get latest blockNum in blockchain
321	latestBlockNum, err := s.ethClient.EthCurrentBlock()
322	if err != nil {
323		return nil, err
324	}
325
326	// TODO: Get CurrentForgerAddr & NextForgerAddr from the Auction SC / Or from the HistoryDB
327
328	// Check if Synchronizer is synchronized
329	status.Synchronized = status.CurrentBlock == latestBlockNum
330	return status, nil
331}
332*/
333
334// rollupSync retreives all the Rollup Smart Contract Data that happened at
335// ethBlock.blockNum with ethBlock.Hash.
336func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, error) {
337	blockNum := ethBlock.EthBlockNum
338	var rollupData = common.NewRollupData()
339	// var forgeL1TxsNum int64
340
341	// Get rollup events in the block, and make sure the block hash matches
342	// the expected one.
343	rollupEvents, blockHash, err := s.ethClient.RollupEventsByBlock(blockNum)
344	if err != nil {
345		return nil, err
346	}
347	// No events in this block
348	if blockHash == nil {
349		return &rollupData, nil
350	}
351	if *blockHash != ethBlock.Hash {
352		log.Errorw("Block hash mismatch in Rollup events", "expected", ethBlock.Hash.String(),
353			"got", blockHash.String())
354		return nil, eth.ErrBlockHashMismatchEvent
355	}
356
357	var nextForgeL1TxsNum int64 // forgeL1TxsNum for the next L1Batch
358	nextForgeL1TxsNumPtr, err := s.historyDB.GetLastL1TxsNum()
359	if err != nil {
360		return nil, err
361	}
362	if nextForgeL1TxsNumPtr != nil {
363		nextForgeL1TxsNum = *nextForgeL1TxsNumPtr + 1
364	} else {
365		nextForgeL1TxsNum = 0
366	}
367
368	// Get L1UserTX
369	rollupData.L1UserTxs, err = getL1UserTx(rollupEvents.L1UserTx, blockNum)
370	if err != nil {
371		return nil, err
372	}
373
374	// Get ForgeBatch events to get the L1CoordinatorTxs
375	for _, evtForgeBatch := range rollupEvents.ForgeBatch {
376		batchData := common.NewBatchData()
377		position := 0
378
379		// Get the input for each Tx
380		forgeBatchArgs, sender, err := s.ethClient.RollupForgeBatchArgs(evtForgeBatch.EthTxHash)
381		if err != nil {
382			return nil, err
383		}
384
385		batchNum := common.BatchNum(evtForgeBatch.BatchNum)
386		var l1UserTxs []common.L1Tx
387		// Check if this is a L1Batch to get L1 Tx from it
388		if forgeBatchArgs.L1Batch {
389			// Get L1UserTxs with toForgeL1TxsNum, which correspond
390			// to the L1UserTxs that are forged in this batch, so
391			// that stateDB can process them.
392
393			// First try to find them in HistoryDB.
394			l1UserTxs, err = s.historyDB.GetL1UserTxs(nextForgeL1TxsNum)
395			if err != nil {
396				return nil, err
397			}
398			// Apart from the DB, try to find them in this block.
399			// This could happen because in a block there could be
400			// multiple batches with L1Batch = true (although it's
401			// a very rare case).  If not found in the DB and the
402			// block doesn't contain the l1UserTxs, it means that
403			// the L1UserTxs queue with toForgeL1TxsNum was closed
404			// empty, so we leave `l1UserTxs` as an empty slice.
405			for _, l1UserTx := range rollupData.L1UserTxs {
406				if *l1UserTx.ToForgeL1TxsNum == nextForgeL1TxsNum {
407					l1UserTxs = append(l1UserTxs, l1UserTx)
408				}
409			}
410
411			position = len(l1UserTxs)
412		}
413		// Get L1 Coordinator Txs
414		for i := range forgeBatchArgs.L1CoordinatorTxs {
415			l1CoordinatorTx := forgeBatchArgs.L1CoordinatorTxs[i]
416			l1CoordinatorTx.Position = position
417			// l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum
418			l1CoordinatorTx.UserOrigin = false
419			l1CoordinatorTx.EthBlockNum = blockNum
420			l1CoordinatorTx.BatchNum = &batchNum
421			l1Tx, err := common.NewL1Tx(&l1CoordinatorTx)
422			if err != nil {
423				return nil, err
424			}
425
426			batchData.L1CoordinatorTxs = append(batchData.L1CoordinatorTxs, *l1Tx)
427			position++
428			// fmt.Println("DGB l1coordtx")
429		}
430
431		// Insert all the txs forged in this batch (l1UserTxs,
432		// L1CoordinatorTxs, PoolL2Txs) into stateDB so that they are
433		// processed.
434		poolL2Txs := common.L2TxsToPoolL2Txs(forgeBatchArgs.L2TxsData) // NOTE: This is a big ugly, find a better way
435
436		// ProcessTxs updates poolL2Txs adding: Nonce (and also TokenID, but we don't use it).
437		processTxsOut, err := s.stateDB.ProcessTxs(forgeBatchArgs.FeeIdxCoordinator, l1UserTxs,
438			batchData.L1CoordinatorTxs, poolL2Txs)
439		if err != nil {
440			return nil, err
441		}
442
443		// Set batchNum in exits
444		for i := range processTxsOut.ExitInfos {
445			exit := &processTxsOut.ExitInfos[i]
446			exit.BatchNum = batchNum
447		}
448		batchData.ExitTree = processTxsOut.ExitInfos
449
450		l2Txs, err := common.PoolL2TxsToL2Txs(poolL2Txs) // NOTE: This is a big uggly, find a better way
451		if err != nil {
452			return nil, err
453		}
454
455		for i := range l2Txs {
456			tx := &l2Txs[i]
457			tx.Position = position
458			tx.EthBlockNum = blockNum
459			tx.BatchNum = batchNum
460			nTx, err := common.NewL2Tx(tx)
461			if err != nil {
462				return nil, err
463			}
464
465			batchData.L2Txs = append(batchData.L2Txs, *nTx)
466			position++
467		}
468
469		for i := range processTxsOut.CreatedAccounts {
470			createdAccount := &processTxsOut.CreatedAccounts[i]
471			createdAccount.Nonce = 0
472			createdAccount.Balance = big.NewInt(0)
473			createdAccount.BatchNum = batchNum
474		}
475		batchData.CreatedAccounts = processTxsOut.CreatedAccounts
476
477		slotNum := int64(0)
478		if ethBlock.EthBlockNum >= s.auctionConstants.GenesisBlockNum {
479			slotNum = (ethBlock.EthBlockNum - s.auctionConstants.GenesisBlockNum) /
480				int64(s.auctionConstants.BlocksPerSlot)
481		}
482
483		// Get Batch information
484		// fmt.Printf("DBG: %#v\n", forgeBatchArgs.FeeIdxCoordinator)
485		batch := common.Batch{
486			BatchNum:           batchNum,
487			EthBlockNum:        blockNum,
488			ForgerAddr:         *sender,
489			CollectedFees:      processTxsOut.CollectedFees,
490			FeeIdxsCoordinator: forgeBatchArgs.FeeIdxCoordinator,
491			StateRoot:          forgeBatchArgs.NewStRoot,
492			NumAccounts:        len(batchData.CreatedAccounts),
493			LastIdx:            forgeBatchArgs.NewLastIdx,
494			ExitRoot:           forgeBatchArgs.NewExitRoot,
495			SlotNum:            slotNum,
496		}
497		nextForgeL1TxsNumCpy := nextForgeL1TxsNum
498		if forgeBatchArgs.L1Batch {
499			batch.ForgeL1TxsNum = &nextForgeL1TxsNumCpy
500			batchData.L1Batch = true
501			nextForgeL1TxsNum++
502		}
503		batchData.Batch = batch
504		rollupData.Batches = append(rollupData.Batches, *batchData)
505	}
506
507	// Get Registered Tokens
508	for _, evtAddToken := range rollupEvents.AddToken {
509		var token common.Token
510
511		token.TokenID = common.TokenID(evtAddToken.TokenID)
512		token.EthAddr = evtAddToken.TokenAddress
513		token.EthBlockNum = blockNum
514
515		if consts, err := s.ethClient.EthERC20Consts(evtAddToken.TokenAddress); err != nil {
516			log.Warnw("Error retreiving ERC20 token constants", "addr", evtAddToken.TokenAddress)
517			token.Name = "ERC20_ETH_ERROR"
518			token.Symbol = "ERROR"
519			token.Decimals = 1
520		} else {
521			token.Name = cutStringMax(consts.Name, 20)
522			token.Symbol = cutStringMax(consts.Symbol, 10)
523			token.Decimals = consts.Decimals
524		}
525
526		rollupData.AddedTokens = append(rollupData.AddedTokens, token)
527	}
528
529	varsUpdate := false
530
531	for _, evtUpdateForgeL1L2BatchTimeout := range rollupEvents.UpdateForgeL1L2BatchTimeout {
532		s.vars.Rollup.ForgeL1L2BatchTimeout = evtUpdateForgeL1L2BatchTimeout.NewForgeL1L2BatchTimeout
533		varsUpdate = true
534	}
535
536	for _, evtUpdateFeeAddToken := range rollupEvents.UpdateFeeAddToken {
537		s.vars.Rollup.FeeAddToken = evtUpdateFeeAddToken.NewFeeAddToken
538		varsUpdate = true
539	}
540
541	// NOTE: WithdrawDelay update doesn't have event, so we can't track changes
542
543	// NOTE: Buckets update dones't have event, so we can't track changes
544
545	for _, evtWithdraw := range rollupEvents.Withdraw {
546		rollupData.Withdrawals = append(rollupData.Withdrawals, common.WithdrawInfo{
547			Idx:             common.Idx(evtWithdraw.Idx),
548			NumExitRoot:     common.BatchNum(evtWithdraw.NumExitRoot),
549			InstantWithdraw: evtWithdraw.InstantWithdraw,
550		})
551	}
552
553	if varsUpdate {
554		s.vars.Rollup.EthBlockNum = blockNum
555		rollupData.Vars = &s.vars.Rollup
556	}
557
558	return &rollupData, nil
559}
560
561func cutStringMax(s string, max int) string {
562	if len(s) > max {
563		return s[:max]
564	}
565	return s
566}
567
568// auctionSync gets information from the Auction Contract
569func (s *Synchronizer) auctionSync(ethBlock *common.Block) (*common.AuctionData, error) {
570	blockNum := ethBlock.EthBlockNum
571	var auctionData = common.NewAuctionData()
572
573	// Get auction events in the block
574	auctionEvents, blockHash, err := s.ethClient.AuctionEventsByBlock(blockNum)
575	if err != nil {
576		return nil, err
577	}
578	// No events in this block
579	if blockHash == nil {
580		return &auctionData, nil
581	}
582	if *blockHash != ethBlock.Hash {
583		log.Errorw("Block hash mismatch in Auction events", "expected", ethBlock.Hash.String(),
584			"got", blockHash.String())
585		return nil, eth.ErrBlockHashMismatchEvent
586	}
587
588	// Get bids
589	for _, evtNewBid := range auctionEvents.NewBid {
590		bid := common.Bid{
591			SlotNum:     evtNewBid.Slot,
592			BidValue:    evtNewBid.BidAmount,
593			Bidder:      evtNewBid.Bidder,
594			EthBlockNum: blockNum,
595		}
596		auctionData.Bids = append(auctionData.Bids, bid)
597	}
598
599	// Get Coordinators
600	for _, evtSetCoordinator := range auctionEvents.SetCoordinator {
601		coordinator := common.Coordinator{
602			Bidder: evtSetCoordinator.BidderAddress,
603			Forger: evtSetCoordinator.ForgerAddress,
604			URL:    evtSetCoordinator.CoordinatorURL,
605		}
606		auctionData.Coordinators = append(auctionData.Coordinators, coordinator)
607	}
608
609	varsUpdate := false
610
611	for _, evt := range auctionEvents.NewSlotDeadline {
612		s.vars.Auction.SlotDeadline = evt.NewSlotDeadline
613		varsUpdate = true
614	}
615	for _, evt := range auctionEvents.NewClosedAuctionSlots {
616		s.vars.Auction.ClosedAuctionSlots = evt.NewClosedAuctionSlots
617		varsUpdate = true
618	}
619	for _, evt := range auctionEvents.NewOutbidding {
620		s.vars.Auction.Outbidding = evt.NewOutbidding
621		varsUpdate = true
622	}
623	for _, evt := range auctionEvents.NewDonationAddress {
624		s.vars.Auction.DonationAddress = evt.NewDonationAddress
625		varsUpdate = true
626	}
627	for _, evt := range auctionEvents.NewBootCoordinator {
628		s.vars.Auction.BootCoordinator = evt.NewBootCoordinator
629		varsUpdate = true
630	}
631	for _, evt := range auctionEvents.NewOpenAuctionSlots {
632		s.vars.Auction.OpenAuctionSlots = evt.NewOpenAuctionSlots
633		varsUpdate = true
634	}
635	for _, evt := range auctionEvents.NewAllocationRatio {
636		s.vars.Auction.AllocationRatio = evt.NewAllocationRatio
637		varsUpdate = true
638	}
639	for _, evt := range auctionEvents.NewDefaultSlotSetBid {
640		if evt.SlotSet > 6 { //nolint:gomnd
641			return nil, fmt.Errorf("unexpected SlotSet in "+
642				"auctionEvents.NewDefaultSlotSetBid: %v", evt.SlotSet)
643		}
644		s.vars.Auction.DefaultSlotSetBid[evt.SlotSet] = evt.NewInitialMinBid
645		varsUpdate = true
646	}
647
648	// NOTE: We ignore NewForgeAllocated
649	// NOTE: We ignore NewForge because we're already tracking ForgeBatch event from Rollup
650	// NOTE: We ignore HEZClaimed
651
652	if varsUpdate {
653		s.vars.Auction.EthBlockNum = blockNum
654		auctionData.Vars = &s.vars.Auction
655	}
656
657	return &auctionData, nil
658}
659
660// wdelayerSync gets information from the Withdrawal Delayer Contract
661func (s *Synchronizer) wdelayerSync(ethBlock *common.Block) (*common.WDelayerData, error) {
662	blockNum := ethBlock.EthBlockNum
663	wDelayerData := common.NewWDelayerData()
664
665	// Get wDelayer events in the block
666	wDelayerEvents, blockHash, err := s.ethClient.WDelayerEventsByBlock(blockNum)
667	if err != nil {
668		return nil, err
669	}
670	// No events in this block
671	if blockHash == nil {
672		return &wDelayerData, nil
673	}
674	if *blockHash != ethBlock.Hash {
675		log.Errorw("Block hash mismatch in WDelayer events", "expected", ethBlock.Hash.String(),
676			"got", blockHash.String())
677		return nil, eth.ErrBlockHashMismatchEvent
678	}
679
680	varsUpdate := false
681
682	// TODO Deposit
683	// TODO Withdraw
684	// TODO EscapeHatchWithdrawal
685	for range wDelayerEvents.EmergencyModeEnabled {
686		s.vars.WDelayer.EmergencyMode = true
687		varsUpdate = true
688	}
689	for _, evt := range wDelayerEvents.NewWithdrawalDelay {
690		s.vars.WDelayer.WithdrawalDelay = evt.WithdrawalDelay
691		varsUpdate = true
692	}
693	for _, evt := range wDelayerEvents.NewHermezKeeperAddress {
694		s.vars.WDelayer.HermezKeeperAddress = evt.NewHermezKeeperAddress
695		varsUpdate = true
696	}
697	for _, evt := range wDelayerEvents.NewWhiteHackGroupAddress {
698		s.vars.WDelayer.WhiteHackGroupAddress = evt.NewWhiteHackGroupAddress
699		varsUpdate = true
700	}
701	for _, evt := range wDelayerEvents.NewHermezGovernanceDAOAddress {
702		s.vars.WDelayer.HermezGovernanceDAOAddress = evt.NewHermezGovernanceDAOAddress
703		varsUpdate = true
704	}
705
706	if varsUpdate {
707		s.vars.WDelayer.EthBlockNum = blockNum
708		wDelayerData.Vars = &s.vars.WDelayer
709	}
710
711	return &wDelayerData, nil
712}
713
714func getL1UserTx(eventsL1UserTx []eth.RollupEventL1UserTx, blockNum int64) ([]common.L1Tx, error) {
715	l1Txs := make([]common.L1Tx, len(eventsL1UserTx))
716	for i := range eventsL1UserTx {
717		eventsL1UserTx[i].L1UserTx.EthBlockNum = blockNum
718		// Check validity of L1UserTx
719		l1Tx, err := common.NewL1Tx(&eventsL1UserTx[i].L1UserTx)
720		if err != nil {
721			return nil, err
722		}
723		l1Txs[i] = *l1Tx
724	}
725	return l1Txs, nil
726}