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