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