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