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