arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/test/ethclient.go
test/ethclient.goRaw
   1package test
   2
   3import (
   4	"context"
   5	"encoding/binary"
   6	"encoding/json"
   7	"fmt"
   8	"math/big"
   9	"reflect"
  10	"sync"
  11	"time"
  12
  13	"github.com/ethereum/go-ethereum"
  14	ethCommon "github.com/ethereum/go-ethereum/common"
  15	"github.com/ethereum/go-ethereum/core/types"
  16	"github.com/hermeznetwork/hermez-node/common"
  17	"github.com/hermeznetwork/hermez-node/eth"
  18	"github.com/hermeznetwork/hermez-node/log"
  19	"github.com/hermeznetwork/tracerr"
  20	"github.com/iden3/go-iden3-crypto/babyjub"
  21	"github.com/mitchellh/copystructure"
  22)
  23
  24func init() {
  25	copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  26		func(raw interface{}) (interface{}, error) {
  27			in := raw.(big.Int)
  28			out := new(big.Int).Set(&in)
  29			return *out, nil
  30		}
  31}
  32
  33// WDelayerBlock stores all the data related to the WDelayer SC from an ethereum block
  34type WDelayerBlock struct {
  35	// State     eth.WDelayerState // TODO
  36	Vars      common.WDelayerVariables
  37	Events    eth.WDelayerEvents
  38	Txs       map[ethCommon.Hash]*types.Transaction
  39	Constants *common.WDelayerConstants
  40	Eth       *EthereumBlock
  41}
  42
  43func (w *WDelayerBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  44	txHash := tx.Hash()
  45	w.Txs[txHash] = tx
  46	return tx
  47}
  48
  49func (w *WDelayerBlock) deposit(txHash ethCommon.Hash, owner, token ethCommon.Address, amount *big.Int) {
  50	w.Events.Deposit = append(w.Events.Deposit, eth.WDelayerEventDeposit{
  51		Owner:            owner,
  52		Token:            token,
  53		Amount:           amount,
  54		DepositTimestamp: uint64(w.Eth.Time),
  55		TxHash:           txHash,
  56	})
  57}
  58
  59// RollupBlock stores all the data related to the Rollup SC from an ethereum block
  60type RollupBlock struct {
  61	State     eth.RollupState
  62	Vars      common.RollupVariables
  63	Events    eth.RollupEvents
  64	Txs       map[ethCommon.Hash]*types.Transaction
  65	Constants *common.RollupConstants
  66	Eth       *EthereumBlock
  67}
  68
  69func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  70	txHash := tx.Hash()
  71	r.Txs[txHash] = tx
  72	return tx
  73}
  74
  75var (
  76	errBidClosed   = fmt.Errorf("Bid has already been closed")
  77	errBidNotOpen  = fmt.Errorf("Bid has not been opened yet")
  78	errBidBelowMin = fmt.Errorf("Bid below minimum")
  79	errCoordNotReg = fmt.Errorf("Coordinator not registered")
  80)
  81
  82// AuctionBlock stores all the data related to the Auction SC from an ethereum block
  83type AuctionBlock struct {
  84	State     eth.AuctionState
  85	Vars      common.AuctionVariables
  86	Events    eth.AuctionEvents
  87	Txs       map[ethCommon.Hash]*types.Transaction
  88	Constants *common.AuctionConstants
  89	Eth       *EthereumBlock
  90}
  91
  92func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  93	txHash := tx.Hash()
  94	a.Txs[txHash] = tx
  95	return tx
  96}
  97
  98func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  99	if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
 100		return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
 101	}
 102	return 0
 103}
 104
 105func (a *AuctionBlock) getCurrentSlotNumber() int64 {
 106	return a.getSlotNumber(a.Eth.BlockNum)
 107}
 108
 109func (a *AuctionBlock) getSlotSet(slot int64) int64 {
 110	return slot % int64(len(a.Vars.DefaultSlotSetBid))
 111}
 112
 113func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
 114	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
 115		return nil, tracerr.Wrap(errBidClosed)
 116	}
 117
 118	slotSet := a.getSlotSet(slot)
 119	// fmt.Println("slot:", slot, "slotSet:", slotSet)
 120	var prevBid *big.Int
 121	slotState, ok := a.State.Slots[slot]
 122	if !ok {
 123		slotState = eth.NewSlotState()
 124		a.State.Slots[slot] = slotState
 125	}
 126	// If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
 127	// bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
 128	if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
 129		prevBid = a.Vars.DefaultSlotSetBid[slotSet]
 130	} else {
 131		prevBid = slotState.BidAmount
 132	}
 133	outBid := new(big.Int).Set(prevBid)
 134	// fmt.Println("outBid:", outBid)
 135	outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
 136	outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
 137	outBid.Add(prevBid, outBid)
 138	// fmt.Println("minBid:", outBid)
 139	return outBid, nil
 140}
 141
 142func (a *AuctionBlock) forge(forger ethCommon.Address) error {
 143	if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
 144		return tracerr.Wrap(err)
 145	} else if !ok {
 146		return tracerr.Wrap(fmt.Errorf("Can't forge"))
 147	}
 148
 149	slotToForge := a.getSlotNumber(a.Eth.BlockNum)
 150	slotState, ok := a.State.Slots[slotToForge]
 151	if !ok {
 152		slotState = eth.NewSlotState()
 153		a.State.Slots[slotToForge] = slotState
 154	}
 155
 156	if !slotState.ForgerCommitment {
 157		// Get the relativeBlock to check if the slotDeadline has been exceeded
 158		relativeBlock := a.Eth.BlockNum - (a.Constants.GenesisBlockNum +
 159			(slotToForge * int64(a.Constants.BlocksPerSlot)))
 160
 161		if relativeBlock < int64(a.Vars.SlotDeadline) {
 162			slotState.ForgerCommitment = true
 163		}
 164	}
 165
 166	slotState.Fulfilled = true
 167
 168	a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
 169		Forger:      forger,
 170		SlotToForge: slotToForge,
 171	})
 172	return nil
 173}
 174
 175func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
 176	if blockNum < a.Constants.GenesisBlockNum {
 177		return false, tracerr.Wrap(fmt.Errorf("Auction has not started yet"))
 178	}
 179
 180	slotToForge := a.getSlotNumber(blockNum)
 181	// fmt.Printf("DBG canForge slot: %v\n", slotToForge)
 182	// Get the relativeBlock to check if the slotDeadline has been exceeded
 183	relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
 184
 185	// If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
 186	// otherwise the one that has been saved will be used
 187	var minBid *big.Int
 188	slotState, ok := a.State.Slots[slotToForge]
 189	if !ok {
 190		slotState = eth.NewSlotState()
 191		a.State.Slots[slotToForge] = slotState
 192	}
 193	if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
 194		minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
 195	} else {
 196		minBid = slotState.ClosedMinBid
 197	}
 198
 199	if !slotState.ForgerCommitment && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
 200		// if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
 201		return true, nil
 202	} else if coord, ok := a.State.Coordinators[slotState.Bidder]; ok &&
 203		coord.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
 204		// if forger bidAmount has exceeded the minBid it can forge
 205		return true, nil
 206	} else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
 207		// if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
 208		return true, nil
 209	} else {
 210		return false, nil
 211	}
 212}
 213
 214// EthereumBlock stores all the generic data related to the an ethereum block
 215type EthereumBlock struct {
 216	BlockNum   int64
 217	Time       int64
 218	Hash       ethCommon.Hash
 219	ParentHash ethCommon.Hash
 220	Tokens     map[ethCommon.Address]eth.ERC20Consts
 221	Nonce      uint64
 222	// state      ethState
 223}
 224
 225// Block represents a ethereum block
 226type Block struct {
 227	Rollup   *RollupBlock
 228	Auction  *AuctionBlock
 229	WDelayer *WDelayerBlock
 230	Eth      *EthereumBlock
 231}
 232
 233func (b *Block) copy() *Block {
 234	bCopyRaw, err := copystructure.Copy(b)
 235	if err != nil {
 236		panic(err)
 237	}
 238	bCopy := bCopyRaw.(*Block)
 239	return bCopy
 240}
 241
 242// Next prepares the successive block.
 243func (b *Block) Next() *Block {
 244	blockNext := b.copy()
 245	blockNext.Rollup.Events = eth.NewRollupEvents()
 246	blockNext.Auction.Events = eth.NewAuctionEvents()
 247
 248	blockNext.Eth.BlockNum = b.Eth.BlockNum + 1
 249	blockNext.Eth.ParentHash = b.Eth.Hash
 250
 251	blockNext.Rollup.Constants = b.Rollup.Constants
 252	blockNext.Auction.Constants = b.Auction.Constants
 253	blockNext.WDelayer.Constants = b.WDelayer.Constants
 254	blockNext.Rollup.Eth = blockNext.Eth
 255	blockNext.Auction.Eth = blockNext.Eth
 256	blockNext.WDelayer.Eth = blockNext.Eth
 257
 258	return blockNext
 259}
 260
 261// ClientSetup is used to initialize the constants of the Smart Contracts and
 262// other details of the test Client
 263type ClientSetup struct {
 264	RollupConstants   *common.RollupConstants
 265	RollupVariables   *common.RollupVariables
 266	AuctionConstants  *common.AuctionConstants
 267	AuctionVariables  *common.AuctionVariables
 268	WDelayerConstants *common.WDelayerConstants
 269	WDelayerVariables *common.WDelayerVariables
 270	VerifyProof       bool
 271}
 272
 273// NewClientSetupExample returns a ClientSetup example with hardcoded realistic
 274// values.  With this setup, the rollup genesis will be block 1, and block 0
 275// and 1 will be premined.
 276//nolint:gomnd
 277func NewClientSetupExample() *ClientSetup {
 278	// rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
 279	// if !ok {
 280	// 	panic("bad rfield")
 281	// }
 282	initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
 283	if !ok {
 284		panic("bad initialMinimalBidding")
 285	}
 286	tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
 287	governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
 288	rollupConstants := &common.RollupConstants{
 289		Verifiers: []common.RollupVerifierStruct{
 290			{
 291				MaxTx:   2048,
 292				NLevels: 32,
 293			},
 294		},
 295		TokenHEZ:                tokenHEZ,
 296		HermezGovernanceAddress: governanceAddress,
 297		HermezAuctionContract:   ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
 298		WithdrawDelayerContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
 299	}
 300	rollupVariables := &common.RollupVariables{
 301		FeeAddToken:           big.NewInt(11),
 302		ForgeL1L2BatchTimeout: 9,
 303		WithdrawalDelay:       80,
 304	}
 305	auctionConstants := &common.AuctionConstants{
 306		BlocksPerSlot:         40,
 307		InitialMinimalBidding: initialMinimalBidding,
 308		GenesisBlockNum:       1,
 309		GovernanceAddress:     governanceAddress,
 310		TokenHEZ:              tokenHEZ,
 311		HermezRollup:          ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
 312	}
 313	auctionVariables := &common.AuctionVariables{
 314		DonationAddress:    ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
 315		BootCoordinator:    ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 316		BootCoordinatorURL: "https://boot.coordinator.com",
 317		DefaultSlotSetBid: [6]*big.Int{
 318			big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
 319			big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
 320		ClosedAuctionSlots: 2,
 321		OpenAuctionSlots:   4320,
 322		AllocationRatio:    [3]uint16{4000, 4000, 2000},
 323		Outbidding:         1000,
 324		SlotDeadline:       20,
 325	}
 326	wDelayerConstants := &common.WDelayerConstants{
 327		MaxWithdrawalDelay:   60 * 60 * 24 * 7 * 2,  // 2 weeks
 328		MaxEmergencyModeTime: 60 * 60 * 24 * 7 * 26, // 26 weeks
 329		HermezRollup:         auctionConstants.HermezRollup,
 330	}
 331	wDelayerVariables := &common.WDelayerVariables{
 332		HermezGovernanceAddress:   ethCommon.HexToAddress("0xcfD0d163AE6432a72682323E2C3A5a69e6B37D12"),
 333		EmergencyCouncilAddress:   ethCommon.HexToAddress("0x2730700932a4FDB97B9268A3Ca29f97Ea5fd7EA0"),
 334		WithdrawalDelay:           60,
 335		EmergencyModeStartingTime: 0,
 336		EmergencyMode:             false,
 337	}
 338	return &ClientSetup{
 339		RollupConstants:   rollupConstants,
 340		RollupVariables:   rollupVariables,
 341		AuctionConstants:  auctionConstants,
 342		AuctionVariables:  auctionVariables,
 343		WDelayerConstants: wDelayerConstants,
 344		WDelayerVariables: wDelayerVariables,
 345	}
 346}
 347
 348// Timer is an interface to simulate a source of time, useful to advance time
 349// virtually.
 350type Timer interface {
 351	Time() int64
 352}
 353
 354// type forgeBatchArgs struct {
 355// 	ethTx     *types.Transaction
 356// 	blockNum  int64
 357// 	blockHash ethCommon.Hash
 358// }
 359
 360type batch struct {
 361	ForgeBatchArgs eth.RollupForgeBatchArgs
 362	Sender         ethCommon.Address
 363}
 364
 365// Client implements the eth.ClientInterface interface, allowing to manipulate the
 366// values for testing, working with deterministic results.
 367type Client struct {
 368	rw                *sync.RWMutex
 369	log               bool
 370	addr              *ethCommon.Address
 371	rollupConstants   *common.RollupConstants
 372	auctionConstants  *common.AuctionConstants
 373	wDelayerConstants *common.WDelayerConstants
 374	blocks            map[int64]*Block
 375	// state            state
 376	blockNum    int64 // last mined block num
 377	maxBlockNum int64 // highest block num calculated
 378	timer       Timer
 379	hasher      hasher
 380
 381	forgeBatchArgsPending map[ethCommon.Hash]*batch
 382	forgeBatchArgs        map[ethCommon.Hash]*batch
 383}
 384
 385// NewClient returns a new test Client that implements the eth.IClient
 386// interface, at the given initialBlockNumber.
 387func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
 388	blocks := make(map[int64]*Block)
 389	blockNum := int64(0)
 390
 391	hasher := hasher{}
 392	// Add ethereum genesis block
 393	mapL1TxQueue := make(map[int64]*eth.QueueStruct)
 394	mapL1TxQueue[0] = eth.NewQueueStruct()
 395	mapL1TxQueue[1] = eth.NewQueueStruct()
 396	blockCurrent := &Block{
 397		Rollup: &RollupBlock{
 398			State: eth.RollupState{
 399				StateRoot:        big.NewInt(0),
 400				ExitRoots:        make([]*big.Int, 1),
 401				ExitNullifierMap: make(map[int64]map[int64]bool),
 402				// TokenID = 0 is ETH.  Set first entry in TokenList with 0x0 address for ETH.
 403				TokenList:              []ethCommon.Address{{}},
 404				TokenMap:               make(map[ethCommon.Address]bool),
 405				MapL1TxQueue:           mapL1TxQueue,
 406				LastL1L2Batch:          0,
 407				CurrentToForgeL1TxsNum: 0,
 408				LastToForgeL1TxsNum:    1,
 409				CurrentIdx:             0,
 410			},
 411			Vars:      *setup.RollupVariables,
 412			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 413			Events:    eth.NewRollupEvents(),
 414			Constants: setup.RollupConstants,
 415		},
 416		Auction: &AuctionBlock{
 417			State: eth.AuctionState{
 418				Slots:           make(map[int64]*eth.SlotState),
 419				PendingBalances: make(map[ethCommon.Address]*big.Int),
 420				Coordinators:    make(map[ethCommon.Address]*eth.Coordinator),
 421			},
 422			Vars:      *setup.AuctionVariables,
 423			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 424			Events:    eth.NewAuctionEvents(),
 425			Constants: setup.AuctionConstants,
 426		},
 427		WDelayer: &WDelayerBlock{
 428			// State: TODO
 429			Vars:      *setup.WDelayerVariables,
 430			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 431			Events:    eth.NewWDelayerEvents(),
 432			Constants: setup.WDelayerConstants,
 433		},
 434		Eth: &EthereumBlock{
 435			BlockNum:   blockNum,
 436			Time:       timer.Time(),
 437			Hash:       hasher.Next(),
 438			ParentHash: ethCommon.Hash{},
 439			Tokens:     make(map[ethCommon.Address]eth.ERC20Consts),
 440		},
 441	}
 442	blockCurrent.Rollup.Eth = blockCurrent.Eth
 443	blockCurrent.Auction.Eth = blockCurrent.Eth
 444	blocks[blockNum] = blockCurrent
 445	blockNext := blockCurrent.Next()
 446	blocks[blockNum+1] = blockNext
 447
 448	c := Client{
 449		rw:                    &sync.RWMutex{},
 450		log:                   l,
 451		addr:                  addr,
 452		rollupConstants:       setup.RollupConstants,
 453		auctionConstants:      setup.AuctionConstants,
 454		wDelayerConstants:     setup.WDelayerConstants,
 455		blocks:                blocks,
 456		timer:                 timer,
 457		hasher:                hasher,
 458		forgeBatchArgsPending: make(map[ethCommon.Hash]*batch),
 459		forgeBatchArgs:        make(map[ethCommon.Hash]*batch),
 460		blockNum:              blockNum,
 461		maxBlockNum:           blockNum,
 462	}
 463
 464	for i := int64(1); i < setup.AuctionConstants.GenesisBlockNum+1; i++ {
 465		c.CtlMineBlock()
 466	}
 467
 468	return &c
 469}
 470
 471//
 472// Mock Control
 473//
 474
 475func (c *Client) setNextBlock(block *Block) {
 476	c.blocks[c.blockNum+1] = block
 477}
 478
 479func (c *Client) revertIfErr(err error, block *Block) {
 480	if err != nil {
 481		log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
 482		c.setNextBlock(block)
 483	}
 484}
 485
 486// Debugf calls log.Debugf if c.log is true
 487func (c *Client) Debugf(template string, args ...interface{}) {
 488	if c.log {
 489		log.Debugf(template, args...)
 490	}
 491}
 492
 493// Debugw calls log.Debugw if c.log is true
 494func (c *Client) Debugw(template string, kv ...interface{}) {
 495	if c.log {
 496		log.Debugw(template, kv...)
 497	}
 498}
 499
 500type hasher struct {
 501	counter uint64
 502}
 503
 504// Next returns the next hash
 505func (h *hasher) Next() ethCommon.Hash {
 506	var hash ethCommon.Hash
 507	binary.LittleEndian.PutUint64(hash[:], h.counter)
 508	h.counter++
 509	return hash
 510}
 511
 512func (c *Client) nextBlock() *Block {
 513	return c.blocks[c.blockNum+1]
 514}
 515
 516func (c *Client) currentBlock() *Block {
 517	return c.blocks[c.blockNum]
 518}
 519
 520// CtlSetAddr sets the address of the client
 521func (c *Client) CtlSetAddr(addr ethCommon.Address) {
 522	c.addr = &addr
 523}
 524
 525// CtlMineBlock moves one block forward
 526func (c *Client) CtlMineBlock() {
 527	c.rw.Lock()
 528	defer c.rw.Unlock()
 529
 530	blockCurrent := c.nextBlock()
 531	c.blockNum++
 532	c.maxBlockNum = c.blockNum
 533	blockCurrent.Eth.Time = c.timer.Time()
 534	blockCurrent.Eth.Hash = c.hasher.Next()
 535	for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
 536		c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
 537	}
 538	c.forgeBatchArgsPending = make(map[ethCommon.Hash]*batch)
 539
 540	blockNext := blockCurrent.Next()
 541	c.blocks[c.blockNum+1] = blockNext
 542	c.Debugw("TestClient mined block", "blockNum", c.blockNum)
 543}
 544
 545// CtlRollback discards the last mined block.  Use this to replace a mined
 546// block to simulate reorgs.
 547func (c *Client) CtlRollback() {
 548	c.rw.Lock()
 549	defer c.rw.Unlock()
 550
 551	if c.blockNum == 0 {
 552		panic("Can't rollback at blockNum = 0")
 553	}
 554	delete(c.blocks, c.blockNum+1) // delete next block
 555	delete(c.blocks, c.blockNum)   // delete current block
 556	c.blockNum--
 557	blockCurrent := c.blocks[c.blockNum]
 558	blockNext := blockCurrent.Next()
 559	c.blocks[c.blockNum+1] = blockNext
 560}
 561
 562//
 563// Ethereum
 564//
 565
 566// CtlLastBlock returns the last blockNum without checks
 567func (c *Client) CtlLastBlock() *common.Block {
 568	c.rw.RLock()
 569	defer c.rw.RUnlock()
 570
 571	block := c.blocks[c.blockNum]
 572	return &common.Block{
 573		Num:        c.blockNum,
 574		Timestamp:  time.Unix(block.Eth.Time, 0),
 575		Hash:       block.Eth.Hash,
 576		ParentHash: block.Eth.ParentHash,
 577	}
 578}
 579
 580// CtlLastForgedBatch returns the last batchNum without checks
 581func (c *Client) CtlLastForgedBatch() int64 {
 582	c.rw.RLock()
 583	defer c.rw.RUnlock()
 584
 585	currentBlock := c.currentBlock()
 586	e := currentBlock.Rollup
 587	return int64(len(e.State.ExitRoots)) - 1
 588}
 589
 590// EthLastBlock returns the last blockNum
 591func (c *Client) EthLastBlock() (int64, error) {
 592	c.rw.RLock()
 593	defer c.rw.RUnlock()
 594
 595	if c.blockNum < c.maxBlockNum {
 596		panic("blockNum has decreased.  " +
 597			"After a rollback you must mine to reach the same or higher blockNum")
 598	}
 599	return c.blockNum, nil
 600}
 601
 602// EthTransactionReceipt returns the transaction receipt of the given txHash
 603func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
 604	c.rw.RLock()
 605	defer c.rw.RUnlock()
 606
 607	for i := int64(0); i < c.blockNum; i++ {
 608		b := c.blocks[i]
 609		_, ok := b.Rollup.Txs[txHash]
 610		if !ok {
 611			_, ok = b.Auction.Txs[txHash]
 612		}
 613		if ok {
 614			return &types.Receipt{
 615				TxHash:      txHash,
 616				Status:      types.ReceiptStatusSuccessful,
 617				BlockHash:   b.Eth.Hash,
 618				BlockNumber: big.NewInt(b.Eth.BlockNum),
 619			}, nil
 620		}
 621	}
 622
 623	return nil, nil
 624}
 625
 626// CtlAddERC20 adds an ERC20 token to the blockchain.
 627func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
 628	nextBlock := c.nextBlock()
 629	e := nextBlock.Eth
 630	e.Tokens[tokenAddr] = constants
 631}
 632
 633// EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
 634func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
 635	currentBlock := c.currentBlock()
 636	e := currentBlock.Eth
 637	if constants, ok := e.Tokens[tokenAddr]; ok {
 638		return &constants, nil
 639	}
 640	return nil, tracerr.Wrap(fmt.Errorf("tokenAddr not found"))
 641}
 642
 643// func newHeader(number *big.Int) *types.Header {
 644// 	return &types.Header{
 645// 		Number: number,
 646// 		Time:   uint64(number.Int64()),
 647// 	}
 648// }
 649
 650// EthHeaderByNumber returns the *types.Header for the given block number in a
 651// deterministic way.
 652// func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
 653// 	return newHeader(number), nil
 654// }
 655
 656// EthBlockByNumber returns the *common.Block for the given block number in a
 657// deterministic way.  If number == -1, the latests known block is returned.
 658func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
 659	c.rw.RLock()
 660	defer c.rw.RUnlock()
 661
 662	if blockNum > c.blockNum {
 663		return nil, ethereum.NotFound
 664	}
 665	if blockNum == -1 {
 666		blockNum = c.blockNum
 667	}
 668	block := c.blocks[blockNum]
 669	return &common.Block{
 670		Num:        blockNum,
 671		Timestamp:  time.Unix(block.Eth.Time, 0),
 672		Hash:       block.Eth.Hash,
 673		ParentHash: block.Eth.ParentHash,
 674	}, nil
 675}
 676
 677// EthAddress returns the ethereum address of the account loaded into the Client
 678func (c *Client) EthAddress() (*ethCommon.Address, error) {
 679	if c.addr == nil {
 680		return nil, tracerr.Wrap(eth.ErrAccountNil)
 681	}
 682	return c.addr, nil
 683}
 684
 685var errTODO = fmt.Errorf("TODO: Not implemented yet")
 686
 687//
 688// Rollup
 689//
 690
 691// CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
 692// func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
 693// 	c.rw.Lock()
 694// 	defer c.rw.Unlock()
 695//
 696// 	nextBlock := c.nextBlock()
 697// 	r := nextBlock.Rollup
 698// 	queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 699// 	if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
 700// 		r.State.LastToForgeL1TxsNum++
 701// 		r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 702// 		queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 703// 	}
 704// 	if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
 705// 		panic("l1Tx.FromIdx > r.State.CurrentIdx")
 706// 	}
 707// 	if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
 708// 		panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
 709// 	}
 710// 	queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
 711// 	r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
 712// 		L1Tx:            *l1Tx,
 713// 		ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
 714// 		Position:        len(queue.L1TxQueue) - 1,
 715// 	})
 716// }
 717
 718// RollupL1UserTxERC20Permit is the interface to call the smart contract function
 719func (c *Client) RollupL1UserTxERC20Permit(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64, deadline *big.Int) (tx *types.Transaction, err error) {
 720	log.Error("TODO")
 721	return nil, tracerr.Wrap(errTODO)
 722}
 723
 724// RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
 725func (c *Client) RollupL1UserTxERC20ETH(
 726	fromBJJ *babyjub.PublicKey,
 727	fromIdx int64,
 728	loadAmount *big.Int,
 729	amount *big.Int,
 730	tokenID uint32,
 731	toIdx int64,
 732) (tx *types.Transaction, err error) {
 733	c.rw.Lock()
 734	defer c.rw.Unlock()
 735	cpy := c.nextBlock().copy()
 736	defer func() { c.revertIfErr(err, cpy) }()
 737
 738	_, err = common.NewFloat16(amount)
 739	if err != nil {
 740		return nil, tracerr.Wrap(err)
 741	}
 742	_, err = common.NewFloat16(loadAmount)
 743	if err != nil {
 744		return nil, tracerr.Wrap(err)
 745	}
 746
 747	nextBlock := c.nextBlock()
 748	r := nextBlock.Rollup
 749	queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 750	if len(queue.L1TxQueue) >= common.RollupConstMaxL1UserTx {
 751		r.State.LastToForgeL1TxsNum++
 752		r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 753		queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 754	}
 755	if fromIdx > r.State.CurrentIdx {
 756		panic("l1Tx.FromIdx > r.State.CurrentIdx")
 757	}
 758	if int(tokenID)+1 > len(r.State.TokenList) {
 759		panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
 760	}
 761	toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
 762	l1Tx, err := common.NewL1Tx(&common.L1Tx{
 763		FromIdx:         common.Idx(fromIdx),
 764		FromEthAddr:     *c.addr,
 765		FromBJJ:         fromBJJ,
 766		Amount:          amount,
 767		LoadAmount:      loadAmount,
 768		TokenID:         common.TokenID(tokenID),
 769		ToIdx:           common.Idx(toIdx),
 770		ToForgeL1TxsNum: &toForgeL1TxsNum,
 771		Position:        len(queue.L1TxQueue),
 772		UserOrigin:      true,
 773	})
 774	if err != nil {
 775		return nil, tracerr.Wrap(err)
 776	}
 777
 778	queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
 779	r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
 780		L1UserTx: *l1Tx,
 781	})
 782	return r.addTransaction(c.newTransaction("l1UserTxERC20ETH", l1Tx)), nil
 783}
 784
 785// RollupL1UserTxERC777 is the interface to call the smart contract function
 786// func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
 787// 	log.Error("TODO")
 788// 	return nil, errTODO
 789// }
 790
 791// RollupRegisterTokensCount is the interface to call the smart contract function
 792func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
 793	log.Error("TODO")
 794	return nil, tracerr.Wrap(errTODO)
 795}
 796
 797// RollupLastForgedBatch is the interface to call the smart contract function
 798func (c *Client) RollupLastForgedBatch() (int64, error) {
 799	c.rw.RLock()
 800	defer c.rw.RUnlock()
 801
 802	currentBlock := c.currentBlock()
 803	e := currentBlock.Rollup
 804	return int64(len(e.State.ExitRoots)) - 1, nil
 805}
 806
 807// RollupWithdrawCircuit is the interface to call the smart contract function
 808func (c *Client) RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int, tokenID uint32, numExitRoot, idx int64, amount *big.Int, instantWithdraw bool) (*types.Transaction, error) {
 809	log.Error("TODO")
 810	return nil, tracerr.Wrap(errTODO)
 811}
 812
 813// RollupWithdrawMerkleProof is the interface to call the smart contract function
 814func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (tx *types.Transaction, err error) {
 815	c.rw.Lock()
 816	defer c.rw.Unlock()
 817	cpy := c.nextBlock().copy()
 818	defer func() { c.revertIfErr(err, cpy) }()
 819
 820	nextBlock := c.nextBlock()
 821	r := nextBlock.Rollup
 822
 823	if int(numExitRoot) >= len(r.State.ExitRoots) {
 824		return nil, tracerr.Wrap(fmt.Errorf("numExitRoot >= len(r.State.ExitRoots)"))
 825	}
 826	if _, ok := r.State.ExitNullifierMap[numExitRoot][idx]; ok {
 827		return nil, tracerr.Wrap(fmt.Errorf("exit already withdrawn"))
 828	}
 829	r.State.ExitNullifierMap[numExitRoot][idx] = true
 830
 831	type data struct {
 832		BabyPubKey      *babyjub.PublicKey
 833		TokenID         uint32
 834		NumExitRoot     int64
 835		Idx             int64
 836		Amount          *big.Int
 837		Siblings        []*big.Int
 838		InstantWithdraw bool
 839	}
 840	tx = r.addTransaction(c.newTransaction("withdrawMerkleProof", data{
 841		BabyPubKey:      babyPubKey,
 842		TokenID:         tokenID,
 843		NumExitRoot:     numExitRoot,
 844		Idx:             idx,
 845		Amount:          amount,
 846		Siblings:        siblings,
 847		InstantWithdraw: instantWithdraw,
 848	}))
 849	r.Events.Withdraw = append(r.Events.Withdraw, eth.RollupEventWithdraw{
 850		Idx:             uint64(idx),
 851		NumExitRoot:     uint64(numExitRoot),
 852		InstantWithdraw: instantWithdraw,
 853		TxHash:          tx.Hash(),
 854	})
 855
 856	if !instantWithdraw {
 857		w := nextBlock.WDelayer
 858		w.deposit(tx.Hash(), *c.addr, r.State.TokenList[int(tokenID)], amount)
 859	}
 860	return tx, nil
 861}
 862
 863type transactionData struct {
 864	Name  string
 865	Value interface{}
 866}
 867
 868func (c *Client) newTransaction(name string, value interface{}) *types.Transaction {
 869	eth := c.nextBlock().Eth
 870	nonce := eth.Nonce
 871	eth.Nonce++
 872	data, err := json.Marshal(transactionData{name, value})
 873	if err != nil {
 874		panic(err)
 875	}
 876	return types.NewTransaction(nonce, ethCommon.Address{}, nil, 0, nil,
 877		data)
 878}
 879
 880// RollupForgeBatch is the interface to call the smart contract function
 881func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
 882	c.rw.Lock()
 883	defer c.rw.Unlock()
 884	cpy := c.nextBlock().copy()
 885	defer func() { c.revertIfErr(err, cpy) }()
 886	if c.addr == nil {
 887		return nil, tracerr.Wrap(eth.ErrAccountNil)
 888	}
 889
 890	a := c.nextBlock().Auction
 891	ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
 892	if err != nil {
 893		return nil, tracerr.Wrap(err)
 894	}
 895	if !ok {
 896		return nil, tracerr.Wrap(fmt.Errorf(common.AuctionErrMsgCannotForge))
 897	}
 898
 899	// TODO: Verify proof
 900
 901	// Auction
 902	err = a.forge(*c.addr)
 903	if err != nil {
 904		return nil, tracerr.Wrap(err)
 905	}
 906
 907	// TODO: If successful, store the tx in a successful array.
 908	// TODO: If failed, store the tx in a failed array.
 909	// TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
 910
 911	return c.addBatch(args)
 912}
 913
 914// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
 915func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
 916	c.rw.Lock()
 917	defer c.rw.Unlock()
 918
 919	if _, err := c.addBatch(args); err != nil {
 920		panic(err)
 921	}
 922}
 923
 924func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
 925	nextBlock := c.nextBlock()
 926	r := nextBlock.Rollup
 927	r.State.StateRoot = args.NewStRoot
 928	if args.NewLastIdx < r.State.CurrentIdx {
 929		return nil, tracerr.Wrap(fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx"))
 930	}
 931	r.State.CurrentIdx = args.NewLastIdx
 932	r.State.ExitNullifierMap[int64(len(r.State.ExitRoots))] = make(map[int64]bool)
 933	r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
 934	if args.L1Batch {
 935		r.State.CurrentToForgeL1TxsNum++
 936		if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
 937			r.State.LastToForgeL1TxsNum++
 938			r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 939		}
 940	}
 941	ethTx := r.addTransaction(c.newTransaction("forgebatch", args))
 942	c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
 943	r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
 944		BatchNum:     int64(len(r.State.ExitRoots)) - 1,
 945		EthTxHash:    ethTx.Hash(),
 946		L1UserTxsLen: uint16(len(args.L1UserTxs)),
 947	})
 948
 949	return ethTx, nil
 950}
 951
 952// RollupAddTokenSimple is a wrapper around RollupAddToken that automatically
 953// sets `deadlie`.
 954func (c *Client) RollupAddTokenSimple(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
 955	return c.RollupAddToken(tokenAddress, feeAddToken, big.NewInt(9999)) //nolint:gomnd
 956}
 957
 958// RollupAddToken is the interface to call the smart contract function
 959func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int,
 960	deadline *big.Int) (tx *types.Transaction, err error) {
 961	c.rw.Lock()
 962	defer c.rw.Unlock()
 963	cpy := c.nextBlock().copy()
 964	defer func() { c.revertIfErr(err, cpy) }()
 965	if c.addr == nil {
 966		return nil, tracerr.Wrap(eth.ErrAccountNil)
 967	}
 968
 969	nextBlock := c.nextBlock()
 970	r := nextBlock.Rollup
 971	if _, ok := r.State.TokenMap[tokenAddress]; ok {
 972		return nil, tracerr.Wrap(fmt.Errorf("Token %v already registered", tokenAddress))
 973	}
 974	if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
 975		return nil, tracerr.Wrap(fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken))
 976	}
 977
 978	r.State.TokenMap[tokenAddress] = true
 979	r.State.TokenList = append(r.State.TokenList, tokenAddress)
 980	r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
 981		TokenID: uint32(len(r.State.TokenList) - 1)})
 982	return r.addTransaction(c.newTransaction("addtoken", tokenAddress)), nil
 983}
 984
 985// RollupGetCurrentTokens is the interface to call the smart contract function
 986func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
 987	c.rw.RLock()
 988	defer c.rw.RUnlock()
 989
 990	log.Error("TODO")
 991	return nil, tracerr.Wrap(errTODO)
 992}
 993
 994// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
 995func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
 996	c.rw.Lock()
 997	defer c.rw.Unlock()
 998	cpy := c.nextBlock().copy()
 999	defer func() { c.revertIfErr(err, cpy) }()
1000	if c.addr == nil {
1001		return nil, tracerr.Wrap(eth.ErrAccountNil)
1002	}
1003
1004	nextBlock := c.nextBlock()
1005	r := nextBlock.Rollup
1006	r.Vars.ForgeL1L2BatchTimeout = newForgeL1Timeout
1007	r.Events.UpdateForgeL1L2BatchTimeout = append(r.Events.UpdateForgeL1L2BatchTimeout,
1008		eth.RollupEventUpdateForgeL1L2BatchTimeout{NewForgeL1L2BatchTimeout: newForgeL1Timeout})
1009
1010	return r.addTransaction(c.newTransaction("updateForgeL1L2BatchTimeout", newForgeL1Timeout)), nil
1011}
1012
1013// RollupUpdateFeeAddToken is the interface to call the smart contract function
1014func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
1015	c.rw.Lock()
1016	defer c.rw.Unlock()
1017	cpy := c.nextBlock().copy()
1018	defer func() { c.revertIfErr(err, cpy) }()
1019	if c.addr == nil {
1020		return nil, tracerr.Wrap(eth.ErrAccountNil)
1021	}
1022
1023	log.Error("TODO")
1024	return nil, tracerr.Wrap(errTODO)
1025}
1026
1027// RollupUpdateTokensHEZ is the interface to call the smart contract function
1028// func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
1029// 	c.rw.Lock()
1030// 	defer c.rw.Unlock()
1031// 	cpy := c.nextBlock().copy()
1032// 	defer func() { c.revertIfErr(err, cpy) }()
1033//
1034// 	log.Error("TODO")
1035// 	return nil, errTODO
1036// }
1037
1038// RollupUpdateGovernance is the interface to call the smart contract function
1039// func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
1040// 	return nil, errTODO
1041// }
1042
1043// RollupConstants returns the Constants of the Rollup Smart Contract
1044func (c *Client) RollupConstants() (*common.RollupConstants, error) {
1045	c.rw.RLock()
1046	defer c.rw.RUnlock()
1047
1048	return c.rollupConstants, nil
1049}
1050
1051// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
1052func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
1053	c.rw.RLock()
1054	defer c.rw.RUnlock()
1055
1056	block, ok := c.blocks[blockNum]
1057	if !ok {
1058		return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1059	}
1060	return &block.Rollup.Events, &block.Eth.Hash, nil
1061}
1062
1063// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
1064func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash, l1UserTxsLen uint16) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
1065	c.rw.RLock()
1066	defer c.rw.RUnlock()
1067
1068	batch, ok := c.forgeBatchArgs[ethTxHash]
1069	if !ok {
1070		return nil, nil, tracerr.Wrap(fmt.Errorf("transaction not found"))
1071	}
1072	return &batch.ForgeBatchArgs, &batch.Sender, nil
1073}
1074
1075//
1076// Auction
1077//
1078
1079// AuctionSetSlotDeadline is the interface to call the smart contract function
1080func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
1081	c.rw.Lock()
1082	defer c.rw.Unlock()
1083	cpy := c.nextBlock().copy()
1084	defer func() { c.revertIfErr(err, cpy) }()
1085	if c.addr == nil {
1086		return nil, tracerr.Wrap(eth.ErrAccountNil)
1087	}
1088
1089	log.Error("TODO")
1090	return nil, tracerr.Wrap(errTODO)
1091}
1092
1093// AuctionGetSlotDeadline is the interface to call the smart contract function
1094func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
1095	c.rw.RLock()
1096	defer c.rw.RUnlock()
1097
1098	log.Error("TODO")
1099	return 0, tracerr.Wrap(errTODO)
1100}
1101
1102// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
1103func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
1104	c.rw.Lock()
1105	defer c.rw.Unlock()
1106	cpy := c.nextBlock().copy()
1107	defer func() { c.revertIfErr(err, cpy) }()
1108	if c.addr == nil {
1109		return nil, tracerr.Wrap(eth.ErrAccountNil)
1110	}
1111
1112	nextBlock := c.nextBlock()
1113	a := nextBlock.Auction
1114	a.Vars.OpenAuctionSlots = newOpenAuctionSlots
1115	a.Events.NewOpenAuctionSlots = append(a.Events.NewOpenAuctionSlots,
1116		eth.AuctionEventNewOpenAuctionSlots{NewOpenAuctionSlots: newOpenAuctionSlots})
1117
1118	return a.addTransaction(c.newTransaction("setOpenAuctionSlots", newOpenAuctionSlots)), nil
1119}
1120
1121// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
1122func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
1123	c.rw.RLock()
1124	defer c.rw.RUnlock()
1125
1126	log.Error("TODO")
1127	return 0, tracerr.Wrap(errTODO)
1128}
1129
1130// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
1131func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
1132	c.rw.Lock()
1133	defer c.rw.Unlock()
1134	cpy := c.nextBlock().copy()
1135	defer func() { c.revertIfErr(err, cpy) }()
1136	if c.addr == nil {
1137		return nil, tracerr.Wrap(eth.ErrAccountNil)
1138	}
1139
1140	log.Error("TODO")
1141	return nil, tracerr.Wrap(errTODO)
1142}
1143
1144// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
1145func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
1146	c.rw.RLock()
1147	defer c.rw.RUnlock()
1148
1149	log.Error("TODO")
1150	return 0, tracerr.Wrap(errTODO)
1151}
1152
1153// AuctionSetOutbidding is the interface to call the smart contract function
1154func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
1155	c.rw.Lock()
1156	defer c.rw.Unlock()
1157	cpy := c.nextBlock().copy()
1158	defer func() { c.revertIfErr(err, cpy) }()
1159	if c.addr == nil {
1160		return nil, tracerr.Wrap(eth.ErrAccountNil)
1161	}
1162
1163	log.Error("TODO")
1164	return nil, tracerr.Wrap(errTODO)
1165}
1166
1167// AuctionGetOutbidding is the interface to call the smart contract function
1168func (c *Client) AuctionGetOutbidding() (uint16, error) {
1169	c.rw.RLock()
1170	defer c.rw.RUnlock()
1171
1172	log.Error("TODO")
1173	return 0, tracerr.Wrap(errTODO)
1174}
1175
1176// AuctionSetAllocationRatio is the interface to call the smart contract function
1177func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
1178	c.rw.Lock()
1179	defer c.rw.Unlock()
1180	cpy := c.nextBlock().copy()
1181	defer func() { c.revertIfErr(err, cpy) }()
1182	if c.addr == nil {
1183		return nil, tracerr.Wrap(eth.ErrAccountNil)
1184	}
1185
1186	log.Error("TODO")
1187	return nil, tracerr.Wrap(errTODO)
1188}
1189
1190// AuctionGetAllocationRatio is the interface to call the smart contract function
1191func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
1192	c.rw.RLock()
1193	defer c.rw.RUnlock()
1194
1195	log.Error("TODO")
1196	return [3]uint16{}, tracerr.Wrap(errTODO)
1197}
1198
1199// AuctionSetDonationAddress is the interface to call the smart contract function
1200func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
1201	c.rw.Lock()
1202	defer c.rw.Unlock()
1203	cpy := c.nextBlock().copy()
1204	defer func() { c.revertIfErr(err, cpy) }()
1205	if c.addr == nil {
1206		return nil, tracerr.Wrap(eth.ErrAccountNil)
1207	}
1208
1209	log.Error("TODO")
1210	return nil, tracerr.Wrap(errTODO)
1211}
1212
1213// AuctionGetDonationAddress is the interface to call the smart contract function
1214func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
1215	c.rw.RLock()
1216	defer c.rw.RUnlock()
1217
1218	log.Error("TODO")
1219	return nil, tracerr.Wrap(errTODO)
1220}
1221
1222// AuctionSetBootCoordinator is the interface to call the smart contract function
1223func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (tx *types.Transaction, err error) {
1224	c.rw.Lock()
1225	defer c.rw.Unlock()
1226	cpy := c.nextBlock().copy()
1227	defer func() { c.revertIfErr(err, cpy) }()
1228	if c.addr == nil {
1229		return nil, tracerr.Wrap(eth.ErrAccountNil)
1230	}
1231
1232	log.Error("TODO")
1233	return nil, tracerr.Wrap(errTODO)
1234}
1235
1236// AuctionGetBootCoordinator is the interface to call the smart contract function
1237func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
1238	c.rw.RLock()
1239	defer c.rw.RUnlock()
1240
1241	currentBlock := c.currentBlock()
1242	a := currentBlock.Auction
1243
1244	return &a.Vars.BootCoordinator, nil
1245}
1246
1247// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
1248func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
1249	c.rw.Lock()
1250	defer c.rw.Unlock()
1251	cpy := c.nextBlock().copy()
1252	defer func() { c.revertIfErr(err, cpy) }()
1253	if c.addr == nil {
1254		return nil, tracerr.Wrap(eth.ErrAccountNil)
1255	}
1256
1257	log.Error("TODO")
1258	return nil, tracerr.Wrap(errTODO)
1259}
1260
1261// AuctionSetCoordinator is the interface to call the smart contract function
1262func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
1263	c.rw.Lock()
1264	defer c.rw.Unlock()
1265	cpy := c.nextBlock().copy()
1266	defer func() { c.revertIfErr(err, cpy) }()
1267	if c.addr == nil {
1268		return nil, tracerr.Wrap(eth.ErrAccountNil)
1269	}
1270
1271	nextBlock := c.nextBlock()
1272	a := nextBlock.Auction
1273
1274	a.State.Coordinators[*c.addr] = &eth.Coordinator{
1275		Forger: forger,
1276		URL:    URL,
1277	}
1278
1279	a.Events.SetCoordinator = append(a.Events.SetCoordinator,
1280		eth.AuctionEventSetCoordinator{
1281			BidderAddress:  *c.addr,
1282			ForgerAddress:  forger,
1283			CoordinatorURL: URL,
1284		})
1285
1286	type data struct {
1287		BidderAddress ethCommon.Address
1288		ForgerAddress ethCommon.Address
1289		URL           string
1290	}
1291	return a.addTransaction(c.newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
1292}
1293
1294// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
1295func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
1296	c.rw.RLock()
1297	defer c.rw.RUnlock()
1298
1299	log.Error("TODO")
1300	return false, tracerr.Wrap(errTODO)
1301}
1302
1303// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
1304func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
1305	c.rw.Lock()
1306	defer c.rw.Unlock()
1307	cpy := c.nextBlock().copy()
1308	defer func() { c.revertIfErr(err, cpy) }()
1309	if c.addr == nil {
1310		return nil, tracerr.Wrap(eth.ErrAccountNil)
1311	}
1312
1313	log.Error("TODO")
1314	return nil, tracerr.Wrap(errTODO)
1315}
1316
1317// AuctionGetSlotNumber is the interface to call the smart contract function
1318func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
1319	c.rw.RLock()
1320	defer c.rw.RUnlock()
1321
1322	currentBlock := c.currentBlock()
1323	a := currentBlock.Auction
1324	return a.getSlotNumber(blockNum), nil
1325}
1326
1327// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
1328func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
1329	c.rw.RLock()
1330	defer c.rw.RUnlock()
1331
1332	log.Error("TODO")
1333	return 0, tracerr.Wrap(errTODO)
1334}
1335
1336// AuctionGetMinBidBySlot is the interface to call the smart contract function
1337func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
1338	c.rw.RLock()
1339	defer c.rw.RUnlock()
1340
1341	log.Error("TODO")
1342	return nil, tracerr.Wrap(errTODO)
1343}
1344
1345// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
1346func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
1347	c.rw.RLock()
1348	defer c.rw.RUnlock()
1349
1350	log.Error("TODO")
1351	return nil, tracerr.Wrap(errTODO)
1352}
1353
1354// AuctionGetSlotSet is the interface to call the smart contract function
1355func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
1356	c.rw.RLock()
1357	defer c.rw.RUnlock()
1358
1359	log.Error("TODO")
1360	return nil, tracerr.Wrap(errTODO)
1361}
1362
1363// AuctionTokensReceived is the interface to call the smart contract function
1364// func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
1365// 	return errTODO
1366// }
1367
1368// AuctionBidSimple is a wrapper around AuctionBid that automatically sets `amount` and `deadline`.
1369func (c *Client) AuctionBidSimple(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
1370	return c.AuctionBid(bidAmount, slot, bidAmount, big.NewInt(99999)) //nolint:gomnd
1371}
1372
1373// AuctionBid is the interface to call the smart contract function.  This
1374// implementation behaves as if any address has infinite tokens.
1375func (c *Client) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
1376	deadline *big.Int) (tx *types.Transaction, err error) {
1377	c.rw.Lock()
1378	defer c.rw.Unlock()
1379	cpy := c.nextBlock().copy()
1380	defer func() { func() { c.revertIfErr(err, cpy) }() }()
1381	if c.addr == nil {
1382		return nil, tracerr.Wrap(eth.ErrAccountNil)
1383	}
1384
1385	nextBlock := c.nextBlock()
1386	a := nextBlock.Auction
1387
1388	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
1389		return nil, tracerr.Wrap(errBidClosed)
1390	}
1391
1392	if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
1393		return nil, tracerr.Wrap(errBidNotOpen)
1394	}
1395
1396	minBid, err := a.getMinBidBySlot(slot)
1397	if err != nil {
1398		return nil, tracerr.Wrap(err)
1399	}
1400	if bidAmount.Cmp(minBid) == -1 {
1401		return nil, tracerr.Wrap(errBidBelowMin)
1402	}
1403
1404	if _, ok := a.State.Coordinators[*c.addr]; !ok {
1405		return nil, tracerr.Wrap(errCoordNotReg)
1406	}
1407
1408	slotState, ok := a.State.Slots[slot]
1409	if !ok {
1410		slotState = eth.NewSlotState()
1411		a.State.Slots[slot] = slotState
1412	}
1413	slotState.Bidder = *c.addr
1414	slotState.BidAmount = bidAmount
1415
1416	a.Events.NewBid = append(a.Events.NewBid,
1417		eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
1418
1419	type data struct {
1420		Slot      int64
1421		BidAmount *big.Int
1422		Bidder    ethCommon.Address
1423	}
1424	return a.addTransaction(c.newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
1425}
1426
1427// AuctionMultiBid is the interface to call the smart contract function.  This
1428// implementation behaves as if any address has infinite tokens.
1429func (c *Client) AuctionMultiBid(amount *big.Int, startingSlot int64, endingSlot int64, slotSet [6]bool,
1430	maxBid, closedMinBid, deadline *big.Int) (tx *types.Transaction, err error) {
1431	c.rw.Lock()
1432	defer c.rw.Unlock()
1433	cpy := c.nextBlock().copy()
1434	defer func() { c.revertIfErr(err, cpy) }()
1435	if c.addr == nil {
1436		return nil, tracerr.Wrap(eth.ErrAccountNil)
1437	}
1438
1439	log.Error("TODO")
1440	return nil, tracerr.Wrap(errTODO)
1441}
1442
1443// AuctionCanForge is the interface to call the smart contract function
1444func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
1445	c.rw.RLock()
1446	defer c.rw.RUnlock()
1447
1448	currentBlock := c.currentBlock()
1449	a := currentBlock.Auction
1450	return a.canForge(forger, blockNum)
1451}
1452
1453// AuctionForge is the interface to call the smart contract function
1454func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
1455	c.rw.Lock()
1456	defer c.rw.Unlock()
1457	cpy := c.nextBlock().copy()
1458	defer func() { c.revertIfErr(err, cpy) }()
1459	if c.addr == nil {
1460		return nil, tracerr.Wrap(eth.ErrAccountNil)
1461	}
1462
1463	log.Error("TODO")
1464	return nil, tracerr.Wrap(errTODO)
1465}
1466
1467// AuctionClaimHEZ is the interface to call the smart contract function
1468func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
1469	c.rw.Lock()
1470	defer c.rw.Unlock()
1471	cpy := c.nextBlock().copy()
1472	defer func() { c.revertIfErr(err, cpy) }()
1473	if c.addr == nil {
1474		return nil, tracerr.Wrap(eth.ErrAccountNil)
1475	}
1476
1477	log.Error("TODO")
1478	return nil, tracerr.Wrap(errTODO)
1479}
1480
1481// AuctionGetClaimableHEZ is the interface to call the smart contract function
1482func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
1483	c.rw.RLock()
1484	defer c.rw.RUnlock()
1485
1486	log.Error("TODO")
1487	return nil, tracerr.Wrap(errTODO)
1488}
1489
1490// AuctionConstants returns the Constants of the Auction Smart Contract
1491func (c *Client) AuctionConstants() (*common.AuctionConstants, error) {
1492	c.rw.RLock()
1493	defer c.rw.RUnlock()
1494
1495	return c.auctionConstants, nil
1496}
1497
1498// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
1499func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
1500	c.rw.RLock()
1501	defer c.rw.RUnlock()
1502
1503	block, ok := c.blocks[blockNum]
1504	if !ok {
1505		return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1506	}
1507	return &block.Auction.Events, &block.Eth.Hash, nil
1508}
1509
1510//
1511// WDelayer
1512//
1513
1514// WDelayerGetHermezGovernanceAddress is the interface to call the smart contract function
1515func (c *Client) WDelayerGetHermezGovernanceAddress() (*ethCommon.Address, error) {
1516	c.rw.RLock()
1517	defer c.rw.RUnlock()
1518
1519	log.Error("TODO")
1520	return nil, tracerr.Wrap(errTODO)
1521}
1522
1523// WDelayerTransferGovernance is the interface to call the smart contract function
1524func (c *Client) WDelayerTransferGovernance(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1525	c.rw.Lock()
1526	defer c.rw.Unlock()
1527	cpy := c.nextBlock().copy()
1528	defer func() { c.revertIfErr(err, cpy) }()
1529	if c.addr == nil {
1530		return nil, tracerr.Wrap(eth.ErrAccountNil)
1531	}
1532
1533	log.Error("TODO")
1534	return nil, tracerr.Wrap(errTODO)
1535}
1536
1537// WDelayerClaimGovernance is the interface to call the smart contract function
1538func (c *Client) WDelayerClaimGovernance() (tx *types.Transaction, err error) {
1539	c.rw.Lock()
1540	defer c.rw.Unlock()
1541	cpy := c.nextBlock().copy()
1542	defer func() { c.revertIfErr(err, cpy) }()
1543	if c.addr == nil {
1544		return nil, tracerr.Wrap(eth.ErrAccountNil)
1545	}
1546
1547	log.Error("TODO")
1548	return nil, tracerr.Wrap(errTODO)
1549}
1550
1551// WDelayerGetEmergencyCouncil is the interface to call the smart contract function
1552func (c *Client) WDelayerGetEmergencyCouncil() (*ethCommon.Address, error) {
1553	c.rw.RLock()
1554	defer c.rw.RUnlock()
1555
1556	log.Error("TODO")
1557	return nil, tracerr.Wrap(errTODO)
1558}
1559
1560// WDelayerTransferEmergencyCouncil is the interface to call the smart contract function
1561func (c *Client) WDelayerTransferEmergencyCouncil(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1562	c.rw.Lock()
1563	defer c.rw.Unlock()
1564	cpy := c.nextBlock().copy()
1565	defer func() { c.revertIfErr(err, cpy) }()
1566	if c.addr == nil {
1567		return nil, tracerr.Wrap(eth.ErrAccountNil)
1568	}
1569
1570	log.Error("TODO")
1571	return nil, tracerr.Wrap(errTODO)
1572}
1573
1574// WDelayerClaimEmergencyCouncil is the interface to call the smart contract function
1575func (c *Client) WDelayerClaimEmergencyCouncil() (tx *types.Transaction, err error) {
1576	c.rw.Lock()
1577	defer c.rw.Unlock()
1578	cpy := c.nextBlock().copy()
1579	defer func() { c.revertIfErr(err, cpy) }()
1580	if c.addr == nil {
1581		return nil, tracerr.Wrap(eth.ErrAccountNil)
1582	}
1583
1584	log.Error("TODO")
1585	return nil, tracerr.Wrap(errTODO)
1586}
1587
1588// WDelayerIsEmergencyMode is the interface to call the smart contract function
1589func (c *Client) WDelayerIsEmergencyMode() (bool, error) {
1590	c.rw.RLock()
1591	defer c.rw.RUnlock()
1592
1593	log.Error("TODO")
1594	return false, tracerr.Wrap(errTODO)
1595}
1596
1597// WDelayerGetWithdrawalDelay is the interface to call the smart contract function
1598func (c *Client) WDelayerGetWithdrawalDelay() (*big.Int, error) {
1599	c.rw.RLock()
1600	defer c.rw.RUnlock()
1601
1602	log.Error("TODO")
1603	return nil, tracerr.Wrap(errTODO)
1604}
1605
1606// WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
1607func (c *Client) WDelayerGetEmergencyModeStartingTime() (*big.Int, error) {
1608	c.rw.RLock()
1609	defer c.rw.RUnlock()
1610
1611	log.Error("TODO")
1612	return nil, tracerr.Wrap(errTODO)
1613}
1614
1615// WDelayerEnableEmergencyMode is the interface to call the smart contract function
1616func (c *Client) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
1617	c.rw.Lock()
1618	defer c.rw.Unlock()
1619	cpy := c.nextBlock().copy()
1620	defer func() { c.revertIfErr(err, cpy) }()
1621	if c.addr == nil {
1622		return nil, tracerr.Wrap(eth.ErrAccountNil)
1623	}
1624
1625	log.Error("TODO")
1626	return nil, tracerr.Wrap(errTODO)
1627}
1628
1629// WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
1630func (c *Client) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction, err error) {
1631	c.rw.Lock()
1632	defer c.rw.Unlock()
1633	cpy := c.nextBlock().copy()
1634	defer func() { c.revertIfErr(err, cpy) }()
1635	if c.addr == nil {
1636		return nil, tracerr.Wrap(eth.ErrAccountNil)
1637	}
1638
1639	nextBlock := c.nextBlock()
1640	w := nextBlock.WDelayer
1641	w.Vars.WithdrawalDelay = newWithdrawalDelay
1642	w.Events.NewWithdrawalDelay = append(w.Events.NewWithdrawalDelay,
1643		eth.WDelayerEventNewWithdrawalDelay{WithdrawalDelay: newWithdrawalDelay})
1644
1645	return w.addTransaction(c.newTransaction("changeWithdrawalDelay", newWithdrawalDelay)), nil
1646}
1647
1648// WDelayerDepositInfo is the interface to call the smart contract function
1649func (c *Client) WDelayerDepositInfo(owner, token ethCommon.Address) (eth.DepositState, error) {
1650	c.rw.RLock()
1651	defer c.rw.RUnlock()
1652
1653	log.Error("TODO")
1654	return eth.DepositState{}, tracerr.Wrap(errTODO)
1655}
1656
1657// WDelayerDeposit is the interface to call the smart contract function
1658func (c *Client) WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
1659	c.rw.Lock()
1660	defer c.rw.Unlock()
1661	cpy := c.nextBlock().copy()
1662	defer func() { c.revertIfErr(err, cpy) }()
1663	if c.addr == nil {
1664		return nil, tracerr.Wrap(eth.ErrAccountNil)
1665	}
1666
1667	log.Error("TODO")
1668	return nil, tracerr.Wrap(errTODO)
1669}
1670
1671// WDelayerWithdrawal is the interface to call the smart contract function
1672func (c *Client) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction, err error) {
1673	c.rw.Lock()
1674	defer c.rw.Unlock()
1675	cpy := c.nextBlock().copy()
1676	defer func() { c.revertIfErr(err, cpy) }()
1677	if c.addr == nil {
1678		return nil, tracerr.Wrap(eth.ErrAccountNil)
1679	}
1680
1681	log.Error("TODO")
1682	return nil, tracerr.Wrap(errTODO)
1683}
1684
1685// WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
1686func (c *Client) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
1687	c.rw.Lock()
1688	defer c.rw.Unlock()
1689	cpy := c.nextBlock().copy()
1690	defer func() { c.revertIfErr(err, cpy) }()
1691	if c.addr == nil {
1692		return nil, tracerr.Wrap(eth.ErrAccountNil)
1693	}
1694
1695	log.Error("TODO")
1696	return nil, tracerr.Wrap(errTODO)
1697}
1698
1699// WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Contract
1700func (c *Client) WDelayerEventsByBlock(blockNum int64) (*eth.WDelayerEvents, *ethCommon.Hash, error) {
1701	c.rw.RLock()
1702	defer c.rw.RUnlock()
1703
1704	block, ok := c.blocks[blockNum]
1705	if !ok {
1706		return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1707	}
1708	return &block.WDelayer.Events, &block.Eth.Hash, nil
1709}
1710
1711// WDelayerConstants returns the Constants of the WDelayer Contract
1712func (c *Client) WDelayerConstants() (*common.WDelayerConstants, error) {
1713	c.rw.RLock()
1714	defer c.rw.RUnlock()
1715
1716	return c.wDelayerConstants, nil
1717}