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	ethCommon "github.com/ethereum/go-ethereum/common"
  14	"github.com/ethereum/go-ethereum/core/types"
  15	"github.com/hermeznetwork/hermez-node/common"
  16	"github.com/hermeznetwork/hermez-node/eth"
  17	"github.com/hermeznetwork/hermez-node/log"
  18	"github.com/iden3/go-iden3-crypto/babyjub"
  19	"github.com/mitchellh/copystructure"
  20)
  21
  22func init() {
  23	copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  24		func(raw interface{}) (interface{}, error) {
  25			in := raw.(big.Int)
  26			out := new(big.Int).Set(&in)
  27			return *out, nil
  28		}
  29}
  30
  31// RollupBlock stores all the data related to the Rollup SC from an ethereum block
  32type RollupBlock struct {
  33	State     eth.RollupState
  34	Vars      eth.RollupVariables
  35	Events    eth.RollupEvents
  36	Txs       map[ethCommon.Hash]*types.Transaction
  37	Constants *eth.RollupPublicConstants
  38	Eth       *EthereumBlock
  39}
  40
  41func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  42	txHash := tx.Hash()
  43	r.Txs[txHash] = tx
  44	return tx
  45}
  46
  47var (
  48	errBidClosed   = fmt.Errorf("Bid has already been closed")
  49	errBidNotOpen  = fmt.Errorf("Bid has not been opened yet")
  50	errBidBelowMin = fmt.Errorf("Bid below minimum")
  51	errCoordNotReg = fmt.Errorf("Coordinator not registered")
  52)
  53
  54// AuctionBlock stores all the data related to the Auction SC from an ethereum block
  55type AuctionBlock struct {
  56	State     eth.AuctionState
  57	Vars      eth.AuctionVariables
  58	Events    eth.AuctionEvents
  59	Txs       map[ethCommon.Hash]*types.Transaction
  60	Constants *eth.AuctionConstants
  61	Eth       *EthereumBlock
  62}
  63
  64func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  65	txHash := tx.Hash()
  66	a.Txs[txHash] = tx
  67	return tx
  68}
  69
  70func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  71	if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
  72		return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
  73	}
  74	return 0
  75}
  76
  77func (a *AuctionBlock) getCurrentSlotNumber() int64 {
  78	return a.getSlotNumber(a.Eth.BlockNum)
  79}
  80
  81func (a *AuctionBlock) getSlotSet(slot int64) int64 {
  82	return slot % int64(len(a.Vars.DefaultSlotSetBid))
  83}
  84
  85func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
  86	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
  87		return nil, errBidClosed
  88	}
  89
  90	slotSet := a.getSlotSet(slot)
  91	// fmt.Println("slot:", slot, "slotSet:", slotSet)
  92	var prevBid *big.Int
  93	slotState, ok := a.State.Slots[slot]
  94	if !ok {
  95		slotState = eth.NewSlotState()
  96		a.State.Slots[slot] = slotState
  97	}
  98	// If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
  99	// bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
 100	if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
 101		prevBid = a.Vars.DefaultSlotSetBid[slotSet]
 102	} else {
 103		prevBid = slotState.BidAmount
 104	}
 105	outBid := new(big.Int).Set(prevBid)
 106	// fmt.Println("outBid:", outBid)
 107	outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
 108	outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
 109	outBid.Add(prevBid, outBid)
 110	// fmt.Println("minBid:", outBid)
 111	return outBid, nil
 112}
 113
 114func (a *AuctionBlock) forge(forger ethCommon.Address) error {
 115	if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
 116		return err
 117	} else if !ok {
 118		return fmt.Errorf("Can't forge")
 119	}
 120
 121	slotToForge := a.getSlotNumber(a.Eth.BlockNum)
 122	slotState, ok := a.State.Slots[slotToForge]
 123	if !ok {
 124		slotState = eth.NewSlotState()
 125		a.State.Slots[slotToForge] = slotState
 126	}
 127	slotState.Fulfilled = true
 128
 129	a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
 130		Forger:      forger,
 131		SlotToForge: slotToForge,
 132	})
 133	return nil
 134}
 135
 136func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
 137	if blockNum < a.Constants.GenesisBlockNum {
 138		return false, fmt.Errorf("Auction has not started yet")
 139	}
 140
 141	slotToForge := a.getSlotNumber(blockNum)
 142	// Get the relativeBlock to check if the slotDeadline has been exceeded
 143	relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
 144
 145	// If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
 146	// otherwise the one that has been saved will be used
 147	var minBid *big.Int
 148	slotState, ok := a.State.Slots[slotToForge]
 149	if !ok {
 150		slotState = eth.NewSlotState()
 151		a.State.Slots[slotToForge] = slotState
 152	}
 153	if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
 154		minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
 155	} else {
 156		minBid = slotState.ClosedMinBid
 157	}
 158
 159	if !slotState.Fulfilled && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
 160		// if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
 161		return true, nil
 162		// TODO, find the forger set by the Bidder
 163	} else if coord, ok := a.State.Coordinators[slotState.Bidder]; ok &&
 164		coord.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
 165		// if forger bidAmount has exceeded the minBid it can forge
 166		return true, nil
 167	} else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
 168		// if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
 169		return true, nil
 170	} else {
 171		return false, nil
 172	}
 173}
 174
 175// EthereumBlock stores all the generic data related to the an ethereum block
 176type EthereumBlock struct {
 177	BlockNum   int64
 178	Time       int64
 179	Hash       ethCommon.Hash
 180	ParentHash ethCommon.Hash
 181	Tokens     map[ethCommon.Address]eth.ERC20Consts
 182	// state      ethState
 183}
 184
 185// Block represents a ethereum block
 186type Block struct {
 187	Rollup  *RollupBlock
 188	Auction *AuctionBlock
 189	Eth     *EthereumBlock
 190}
 191
 192func (b *Block) copy() *Block {
 193	bCopyRaw, err := copystructure.Copy(b)
 194	if err != nil {
 195		panic(err)
 196	}
 197	bCopy := bCopyRaw.(*Block)
 198	return bCopy
 199}
 200
 201// Next prepares the successive block.
 202func (b *Block) Next() *Block {
 203	blockNext := b.copy()
 204	blockNext.Rollup.Events = eth.NewRollupEvents()
 205	blockNext.Auction.Events = eth.NewAuctionEvents()
 206
 207	blockNext.Eth.BlockNum = b.Eth.BlockNum + 1
 208	blockNext.Eth.ParentHash = b.Eth.Hash
 209
 210	blockNext.Rollup.Constants = b.Rollup.Constants
 211	blockNext.Auction.Constants = b.Auction.Constants
 212	blockNext.Rollup.Eth = blockNext.Eth
 213	blockNext.Auction.Eth = blockNext.Eth
 214
 215	return blockNext
 216}
 217
 218// ClientSetup is used to initialize the constants of the Smart Contracts and
 219// other details of the test Client
 220type ClientSetup struct {
 221	RollupConstants  *eth.RollupPublicConstants
 222	RollupVariables  *eth.RollupVariables
 223	AuctionConstants *eth.AuctionConstants
 224	AuctionVariables *eth.AuctionVariables
 225	VerifyProof      bool
 226}
 227
 228// NewClientSetupExample returns a ClientSetup example with hardcoded realistic values.
 229//nolint:gomnd
 230func NewClientSetupExample() *ClientSetup {
 231	// rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
 232	// if !ok {
 233	// 	panic("bad rfield")
 234	// }
 235	initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
 236	if !ok {
 237		panic("bad initialMinimalBidding")
 238	}
 239	tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
 240	governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
 241	rollupConstants := &eth.RollupPublicConstants{
 242		Verifiers: []eth.RollupVerifierStruct{
 243			{
 244				MaxTx:   2048,
 245				NLevels: 32,
 246			},
 247		},
 248		TokenHEZ:                   tokenHEZ,
 249		HermezGovernanceDAOAddress: governanceAddress,
 250		SafetyAddress:              ethCommon.HexToAddress("0x84d8B79E84fe87B14ad61A554e740f6736bF4c20"),
 251		HermezAuctionContract:      ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
 252		WithdrawDelayerContract:    ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
 253	}
 254	rollupVariables := &eth.RollupVariables{
 255		FeeAddToken:           big.NewInt(11),
 256		ForgeL1L2BatchTimeout: 9,
 257		WithdrawalDelay:       80,
 258	}
 259	auctionConstants := &eth.AuctionConstants{
 260		BlocksPerSlot:         40,
 261		InitialMinimalBidding: initialMinimalBidding,
 262		GenesisBlockNum:       0,
 263		GovernanceAddress:     governanceAddress,
 264		TokenHEZ:              tokenHEZ,
 265		HermezRollup:          ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
 266	}
 267	auctionVariables := &eth.AuctionVariables{
 268		DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
 269		BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 270		DefaultSlotSetBid: [6]*big.Int{
 271			big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
 272			big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
 273		ClosedAuctionSlots: 2,
 274		OpenAuctionSlots:   4320,
 275		AllocationRatio:    [3]uint16{4000, 4000, 2000},
 276		Outbidding:         1000,
 277		SlotDeadline:       20,
 278	}
 279	return &ClientSetup{
 280		RollupConstants:  rollupConstants,
 281		RollupVariables:  rollupVariables,
 282		AuctionConstants: auctionConstants,
 283		AuctionVariables: auctionVariables,
 284	}
 285}
 286
 287// Timer is an interface to simulate a source of time, useful to advance time
 288// virtually.
 289type Timer interface {
 290	Time() int64
 291}
 292
 293// type forgeBatchArgs struct {
 294// 	ethTx     *types.Transaction
 295// 	blockNum  int64
 296// 	blockHash ethCommon.Hash
 297// }
 298
 299// Client implements the eth.ClientInterface interface, allowing to manipulate the
 300// values for testing, working with deterministic results.
 301type Client struct {
 302	rw               *sync.RWMutex
 303	log              bool
 304	addr             *ethCommon.Address
 305	rollupConstants  *eth.RollupPublicConstants
 306	auctionConstants *eth.AuctionConstants
 307	blocks           map[int64]*Block
 308	// state            state
 309	blockNum    int64 // last mined block num
 310	maxBlockNum int64 // highest block num calculated
 311	timer       Timer
 312	hasher      hasher
 313
 314	forgeBatchArgsPending map[ethCommon.Hash]*eth.RollupForgeBatchArgs
 315	forgeBatchArgs        map[ethCommon.Hash]*eth.RollupForgeBatchArgs
 316}
 317
 318// NewClient returns a new test Client that implements the eth.IClient
 319// interface, at the given initialBlockNumber.
 320func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
 321	blocks := make(map[int64]*Block)
 322	blockNum := int64(0)
 323
 324	hasher := hasher{}
 325	// Add ethereum genesis block
 326	mapL1TxQueue := make(map[int64]*eth.QueueStruct)
 327	mapL1TxQueue[0] = eth.NewQueueStruct()
 328	mapL1TxQueue[1] = eth.NewQueueStruct()
 329	blockCurrent := Block{
 330		Rollup: &RollupBlock{
 331			State: eth.RollupState{
 332				StateRoot:        big.NewInt(0),
 333				ExitRoots:        make([]*big.Int, 0),
 334				ExitNullifierMap: make(map[[256 / 8]byte]bool),
 335				// TokenID = 0 is ETH.  Set first entry in TokenList with 0x0 address for ETH.
 336				TokenList:              []ethCommon.Address{{}},
 337				TokenMap:               make(map[ethCommon.Address]bool),
 338				MapL1TxQueue:           mapL1TxQueue,
 339				LastL1L2Batch:          0,
 340				CurrentToForgeL1TxsNum: 0,
 341				LastToForgeL1TxsNum:    1,
 342				CurrentIdx:             0,
 343			},
 344			Vars:      *setup.RollupVariables,
 345			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 346			Events:    eth.NewRollupEvents(),
 347			Constants: setup.RollupConstants,
 348		},
 349		Auction: &AuctionBlock{
 350			State: eth.AuctionState{
 351				Slots:           make(map[int64]*eth.SlotState),
 352				PendingBalances: make(map[ethCommon.Address]*big.Int),
 353				Coordinators:    make(map[ethCommon.Address]*eth.Coordinator),
 354			},
 355			Vars:      *setup.AuctionVariables,
 356			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 357			Events:    eth.NewAuctionEvents(),
 358			Constants: setup.AuctionConstants,
 359		},
 360		Eth: &EthereumBlock{
 361			BlockNum:   blockNum,
 362			Time:       timer.Time(),
 363			Hash:       hasher.Next(),
 364			ParentHash: ethCommon.Hash{},
 365			Tokens:     make(map[ethCommon.Address]eth.ERC20Consts),
 366		},
 367	}
 368	blockCurrent.Rollup.Eth = blockCurrent.Eth
 369	blockCurrent.Auction.Eth = blockCurrent.Eth
 370	blocks[blockNum] = &blockCurrent
 371	blockNext := blockCurrent.Next()
 372	blocks[blockNum+1] = blockNext
 373
 374	return &Client{
 375		rw:                    &sync.RWMutex{},
 376		log:                   l,
 377		addr:                  addr,
 378		rollupConstants:       setup.RollupConstants,
 379		auctionConstants:      setup.AuctionConstants,
 380		blocks:                blocks,
 381		timer:                 timer,
 382		hasher:                hasher,
 383		forgeBatchArgsPending: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
 384		forgeBatchArgs:        make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
 385	}
 386}
 387
 388//
 389// Mock Control
 390//
 391
 392func (c *Client) setNextBlock(block *Block) {
 393	c.blocks[c.blockNum+1] = block
 394}
 395
 396func (c *Client) revertIfErr(err error, block *Block) {
 397	if err != nil {
 398		log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
 399		c.setNextBlock(block)
 400	}
 401}
 402
 403// Debugf calls log.Debugf if c.log is true
 404func (c *Client) Debugf(template string, args ...interface{}) {
 405	if c.log {
 406		log.Debugf(template, args...)
 407	}
 408}
 409
 410// Debugw calls log.Debugw if c.log is true
 411func (c *Client) Debugw(template string, kv ...interface{}) {
 412	if c.log {
 413		log.Debugw(template, kv...)
 414	}
 415}
 416
 417type hasher struct {
 418	counter uint64
 419}
 420
 421// Next returns the next hash
 422func (h *hasher) Next() ethCommon.Hash {
 423	var hash ethCommon.Hash
 424	binary.LittleEndian.PutUint64(hash[:], h.counter)
 425	h.counter++
 426	return hash
 427}
 428
 429func (c *Client) nextBlock() *Block {
 430	return c.blocks[c.blockNum+1]
 431}
 432
 433func (c *Client) currentBlock() *Block {
 434	return c.blocks[c.blockNum]
 435}
 436
 437// CtlSetAddr sets the address of the client
 438func (c *Client) CtlSetAddr(addr ethCommon.Address) {
 439	c.addr = &addr
 440}
 441
 442// CtlMineBlock moves one block forward
 443func (c *Client) CtlMineBlock() {
 444	c.rw.Lock()
 445	defer c.rw.Unlock()
 446
 447	blockCurrent := c.nextBlock()
 448	c.blockNum++
 449	c.maxBlockNum = c.blockNum
 450	blockCurrent.Eth.Time = c.timer.Time()
 451	blockCurrent.Eth.Hash = c.hasher.Next()
 452	for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
 453		c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
 454	}
 455	c.forgeBatchArgsPending = make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs)
 456
 457	blockNext := blockCurrent.Next()
 458	c.blocks[c.blockNum+1] = blockNext
 459	c.Debugw("TestClient mined block", "blockNum", c.blockNum)
 460}
 461
 462// CtlRollback discards the last mined block.  Use this to replace a mined
 463// block to simulate reorgs.
 464func (c *Client) CtlRollback() {
 465	c.rw.Lock()
 466	defer c.rw.Unlock()
 467
 468	if c.blockNum == 0 {
 469		panic("Can't rollback at blockNum = 0")
 470	}
 471	delete(c.blocks, c.blockNum+1) // delete next block
 472	delete(c.blocks, c.blockNum)   // delete current block
 473	c.blockNum--
 474	blockCurrent := c.blocks[c.blockNum]
 475	blockNext := blockCurrent.Next()
 476	c.blocks[c.blockNum+1] = blockNext
 477}
 478
 479//
 480// Ethereum
 481//
 482
 483// EthCurrentBlock returns the current blockNum
 484func (c *Client) EthCurrentBlock() (int64, error) {
 485	c.rw.RLock()
 486	defer c.rw.RUnlock()
 487
 488	if c.blockNum < c.maxBlockNum {
 489		panic("blockNum has decreased.  " +
 490			"After a rollback you must mine to reach the same or higher blockNum")
 491	}
 492	return c.blockNum, nil
 493}
 494
 495// EthTransactionReceipt returns the transaction receipt of the given txHash
 496func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
 497	c.rw.RLock()
 498	defer c.rw.RUnlock()
 499
 500	for i := int64(0); i < c.blockNum; i++ {
 501		b := c.blocks[i]
 502		_, ok := b.Rollup.Txs[txHash]
 503		if !ok {
 504			_, ok = b.Auction.Txs[txHash]
 505		}
 506		if ok {
 507			return &types.Receipt{
 508				TxHash:      txHash,
 509				Status:      types.ReceiptStatusSuccessful,
 510				BlockHash:   b.Eth.Hash,
 511				BlockNumber: big.NewInt(b.Eth.BlockNum),
 512			}, nil
 513		}
 514	}
 515
 516	return nil, nil
 517}
 518
 519// CtlAddERC20 adds an ERC20 token to the blockchain.
 520func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
 521	nextBlock := c.nextBlock()
 522	e := nextBlock.Eth
 523	e.Tokens[tokenAddr] = constants
 524}
 525
 526// EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
 527func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
 528	currentBlock := c.currentBlock()
 529	e := currentBlock.Eth
 530	if constants, ok := e.Tokens[tokenAddr]; ok {
 531		return &constants, nil
 532	}
 533	return nil, fmt.Errorf("tokenAddr not found")
 534}
 535
 536// func newHeader(number *big.Int) *types.Header {
 537// 	return &types.Header{
 538// 		Number: number,
 539// 		Time:   uint64(number.Int64()),
 540// 	}
 541// }
 542
 543// EthHeaderByNumber returns the *types.Header for the given block number in a
 544// deterministic way.
 545// func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
 546// 	return newHeader(number), nil
 547// }
 548
 549// EthBlockByNumber returns the *common.Block for the given block number in a
 550// deterministic way.
 551func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
 552	c.rw.RLock()
 553	defer c.rw.RUnlock()
 554
 555	block, ok := c.blocks[blockNum]
 556	if !ok {
 557		return nil, fmt.Errorf("block not found")
 558	}
 559	return &common.Block{
 560		EthBlockNum: blockNum,
 561		Timestamp:   time.Unix(block.Eth.Time, 0),
 562		Hash:        block.Eth.Hash,
 563		ParentHash:  block.Eth.ParentHash,
 564	}, nil
 565}
 566
 567// EthAddress returns the ethereum address of the account loaded into the Client
 568func (c *Client) EthAddress() (*ethCommon.Address, error) {
 569	if c.addr == nil {
 570		return nil, eth.ErrAccountNil
 571	}
 572	return c.addr, nil
 573}
 574
 575var errTODO = fmt.Errorf("TODO: Not implemented yet")
 576
 577//
 578// Rollup
 579//
 580
 581// CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
 582func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
 583	c.rw.Lock()
 584	defer c.rw.Unlock()
 585
 586	nextBlock := c.nextBlock()
 587	r := nextBlock.Rollup
 588	queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 589	if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
 590		r.State.LastToForgeL1TxsNum++
 591		r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 592		queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 593	}
 594	if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
 595		panic("l1Tx.FromIdx > r.State.CurrentIdx")
 596	}
 597	if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
 598		panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
 599	}
 600	queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
 601	r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
 602		L1UserTx:        *l1Tx,
 603		ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
 604		Position:        len(queue.L1TxQueue) - 1,
 605	})
 606}
 607
 608// RollupL1UserTxERC20ETH is the interface to call the smart contract function
 609func (c *Client) RollupL1UserTxERC20ETH(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
 610	log.Error("TODO")
 611	return nil, errTODO
 612}
 613
 614// RollupL1UserTxERC777 is the interface to call the smart contract function
 615func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
 616	log.Error("TODO")
 617	return nil, errTODO
 618}
 619
 620// RollupRegisterTokensCount is the interface to call the smart contract function
 621func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
 622	log.Error("TODO")
 623	return nil, errTODO
 624}
 625
 626// RollupWithdrawCircuit is the interface to call the smart contract function
 627func (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) {
 628	log.Error("TODO")
 629	return nil, errTODO
 630}
 631
 632// RollupWithdrawMerkleProof is the interface to call the smart contract function
 633func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction, error) {
 634	log.Error("TODO")
 635	return nil, errTODO
 636}
 637
 638type transactionData struct {
 639	Name  string
 640	Value interface{}
 641}
 642
 643func newTransaction(name string, value interface{}) *types.Transaction {
 644	data, err := json.Marshal(transactionData{name, value})
 645	if err != nil {
 646		panic(err)
 647	}
 648	return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
 649		data)
 650}
 651
 652// RollupForgeBatch is the interface to call the smart contract function
 653func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
 654	c.rw.Lock()
 655	defer c.rw.Unlock()
 656	cpy := c.nextBlock().copy()
 657	defer func() { c.revertIfErr(err, cpy) }()
 658	if c.addr == nil {
 659		return nil, eth.ErrAccountNil
 660	}
 661
 662	a := c.nextBlock().Auction
 663	ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
 664	if err != nil {
 665		return nil, err
 666	}
 667	if !ok {
 668		return nil, fmt.Errorf("incorrect slot")
 669	}
 670
 671	// TODO: Verify proof
 672
 673	// Auction
 674	err = a.forge(*c.addr)
 675	if err != nil {
 676		return nil, err
 677	}
 678
 679	// TODO: If successful, store the tx in a successful array.
 680	// TODO: If failed, store the tx in a failed array.
 681	// TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
 682
 683	return c.addBatch(args)
 684}
 685
 686// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
 687func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
 688	c.rw.Lock()
 689	defer c.rw.Unlock()
 690
 691	if _, err := c.addBatch(args); err != nil {
 692		panic(err)
 693	}
 694}
 695
 696func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
 697	nextBlock := c.nextBlock()
 698	r := nextBlock.Rollup
 699	r.State.StateRoot = args.NewStRoot
 700	if args.NewLastIdx < r.State.CurrentIdx {
 701		return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
 702	}
 703	r.State.CurrentIdx = args.NewLastIdx
 704	r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
 705	if args.L1Batch {
 706		r.State.CurrentToForgeL1TxsNum++
 707		if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
 708			r.State.LastToForgeL1TxsNum++
 709			r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 710		}
 711	}
 712	ethTx := r.addTransaction(newTransaction("forgebatch", args))
 713	c.forgeBatchArgsPending[ethTx.Hash()] = args
 714	r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
 715		BatchNum:  int64(len(r.State.ExitRoots)),
 716		EthTxHash: ethTx.Hash(),
 717	})
 718
 719	return ethTx, nil
 720}
 721
 722// RollupAddToken is the interface to call the smart contract function
 723func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
 724	c.rw.Lock()
 725	defer c.rw.Unlock()
 726	cpy := c.nextBlock().copy()
 727	defer func() { c.revertIfErr(err, cpy) }()
 728	if c.addr == nil {
 729		return nil, eth.ErrAccountNil
 730	}
 731
 732	nextBlock := c.nextBlock()
 733	r := nextBlock.Rollup
 734	if _, ok := r.State.TokenMap[tokenAddress]; ok {
 735		return nil, fmt.Errorf("Token %v already registered", tokenAddress)
 736	}
 737	if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
 738		return nil, fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken)
 739	}
 740
 741	r.State.TokenMap[tokenAddress] = true
 742	r.State.TokenList = append(r.State.TokenList, tokenAddress)
 743	r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
 744		TokenID: uint32(len(r.State.TokenList) - 1)})
 745	return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
 746}
 747
 748// RollupGetCurrentTokens is the interface to call the smart contract function
 749func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
 750	c.rw.RLock()
 751	defer c.rw.RUnlock()
 752
 753	log.Error("TODO")
 754	return nil, errTODO
 755}
 756
 757// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
 758func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
 759	c.rw.Lock()
 760	defer c.rw.Unlock()
 761	cpy := c.nextBlock().copy()
 762	defer func() { c.revertIfErr(err, cpy) }()
 763	if c.addr == nil {
 764		return nil, eth.ErrAccountNil
 765	}
 766
 767	log.Error("TODO")
 768	return nil, errTODO
 769}
 770
 771// RollupUpdateFeeAddToken is the interface to call the smart contract function
 772func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
 773	c.rw.Lock()
 774	defer c.rw.Unlock()
 775	cpy := c.nextBlock().copy()
 776	defer func() { c.revertIfErr(err, cpy) }()
 777	if c.addr == nil {
 778		return nil, eth.ErrAccountNil
 779	}
 780
 781	log.Error("TODO")
 782	return nil, errTODO
 783}
 784
 785// RollupUpdateTokensHEZ is the interface to call the smart contract function
 786// func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
 787// 	c.rw.Lock()
 788// 	defer c.rw.Unlock()
 789// 	cpy := c.nextBlock().copy()
 790// 	defer func() { c.revertIfErr(err, cpy) }()
 791//
 792// 	log.Error("TODO")
 793// 	return nil, errTODO
 794// }
 795
 796// RollupUpdateGovernance is the interface to call the smart contract function
 797// func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
 798// 	return nil, errTODO
 799// }
 800
 801// RollupConstants returns the Constants of the Rollup Smart Contract
 802func (c *Client) RollupConstants() (*eth.RollupPublicConstants, error) {
 803	c.rw.RLock()
 804	defer c.rw.RUnlock()
 805
 806	log.Error("TODO")
 807	return nil, errTODO
 808}
 809
 810// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
 811func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
 812	c.rw.RLock()
 813	defer c.rw.RUnlock()
 814
 815	block, ok := c.blocks[blockNum]
 816	if !ok {
 817		return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
 818	}
 819	return &block.Rollup.Events, &block.Eth.Hash, nil
 820}
 821
 822// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
 823func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, error) {
 824	c.rw.RLock()
 825	defer c.rw.RUnlock()
 826
 827	forgeBatchArgs, ok := c.forgeBatchArgs[ethTxHash]
 828	if !ok {
 829		return nil, fmt.Errorf("transaction not found")
 830	}
 831	return forgeBatchArgs, nil
 832}
 833
 834//
 835// Auction
 836//
 837
 838// AuctionSetSlotDeadline is the interface to call the smart contract function
 839func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
 840	c.rw.Lock()
 841	defer c.rw.Unlock()
 842	cpy := c.nextBlock().copy()
 843	defer func() { c.revertIfErr(err, cpy) }()
 844	if c.addr == nil {
 845		return nil, eth.ErrAccountNil
 846	}
 847
 848	log.Error("TODO")
 849	return nil, errTODO
 850}
 851
 852// AuctionGetSlotDeadline is the interface to call the smart contract function
 853func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
 854	c.rw.RLock()
 855	defer c.rw.RUnlock()
 856
 857	log.Error("TODO")
 858	return 0, errTODO
 859}
 860
 861// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
 862func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
 863	c.rw.Lock()
 864	defer c.rw.Unlock()
 865	cpy := c.nextBlock().copy()
 866	defer func() { c.revertIfErr(err, cpy) }()
 867	if c.addr == nil {
 868		return nil, eth.ErrAccountNil
 869	}
 870
 871	log.Error("TODO")
 872	return nil, errTODO
 873}
 874
 875// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
 876func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
 877	c.rw.RLock()
 878	defer c.rw.RUnlock()
 879
 880	log.Error("TODO")
 881	return 0, errTODO
 882}
 883
 884// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
 885func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
 886	c.rw.Lock()
 887	defer c.rw.Unlock()
 888	cpy := c.nextBlock().copy()
 889	defer func() { c.revertIfErr(err, cpy) }()
 890	if c.addr == nil {
 891		return nil, eth.ErrAccountNil
 892	}
 893
 894	log.Error("TODO")
 895	return nil, errTODO
 896}
 897
 898// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
 899func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
 900	c.rw.RLock()
 901	defer c.rw.RUnlock()
 902
 903	log.Error("TODO")
 904	return 0, errTODO
 905}
 906
 907// AuctionSetOutbidding is the interface to call the smart contract function
 908func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
 909	c.rw.Lock()
 910	defer c.rw.Unlock()
 911	cpy := c.nextBlock().copy()
 912	defer func() { c.revertIfErr(err, cpy) }()
 913	if c.addr == nil {
 914		return nil, eth.ErrAccountNil
 915	}
 916
 917	log.Error("TODO")
 918	return nil, errTODO
 919}
 920
 921// AuctionGetOutbidding is the interface to call the smart contract function
 922func (c *Client) AuctionGetOutbidding() (uint16, error) {
 923	c.rw.RLock()
 924	defer c.rw.RUnlock()
 925
 926	log.Error("TODO")
 927	return 0, errTODO
 928}
 929
 930// AuctionSetAllocationRatio is the interface to call the smart contract function
 931func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
 932	c.rw.Lock()
 933	defer c.rw.Unlock()
 934	cpy := c.nextBlock().copy()
 935	defer func() { c.revertIfErr(err, cpy) }()
 936	if c.addr == nil {
 937		return nil, eth.ErrAccountNil
 938	}
 939
 940	log.Error("TODO")
 941	return nil, errTODO
 942}
 943
 944// AuctionGetAllocationRatio is the interface to call the smart contract function
 945func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
 946	c.rw.RLock()
 947	defer c.rw.RUnlock()
 948
 949	log.Error("TODO")
 950	return [3]uint16{}, errTODO
 951}
 952
 953// AuctionSetDonationAddress is the interface to call the smart contract function
 954func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
 955	c.rw.Lock()
 956	defer c.rw.Unlock()
 957	cpy := c.nextBlock().copy()
 958	defer func() { c.revertIfErr(err, cpy) }()
 959	if c.addr == nil {
 960		return nil, eth.ErrAccountNil
 961	}
 962
 963	log.Error("TODO")
 964	return nil, errTODO
 965}
 966
 967// AuctionGetDonationAddress is the interface to call the smart contract function
 968func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
 969	c.rw.RLock()
 970	defer c.rw.RUnlock()
 971
 972	log.Error("TODO")
 973	return nil, errTODO
 974}
 975
 976// AuctionSetBootCoordinator is the interface to call the smart contract function
 977func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
 978	c.rw.Lock()
 979	defer c.rw.Unlock()
 980	cpy := c.nextBlock().copy()
 981	defer func() { c.revertIfErr(err, cpy) }()
 982	if c.addr == nil {
 983		return nil, eth.ErrAccountNil
 984	}
 985
 986	log.Error("TODO")
 987	return nil, errTODO
 988}
 989
 990// AuctionGetBootCoordinator is the interface to call the smart contract function
 991func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
 992	c.rw.RLock()
 993	defer c.rw.RUnlock()
 994
 995	currentBlock := c.currentBlock()
 996	a := currentBlock.Auction
 997
 998	return &a.Vars.BootCoordinator, nil
 999}
1000
1001// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
1002func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
1003	c.rw.Lock()
1004	defer c.rw.Unlock()
1005	cpy := c.nextBlock().copy()
1006	defer func() { c.revertIfErr(err, cpy) }()
1007	if c.addr == nil {
1008		return nil, eth.ErrAccountNil
1009	}
1010
1011	log.Error("TODO")
1012	return nil, errTODO
1013}
1014
1015// AuctionSetCoordinator is the interface to call the smart contract function
1016func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
1017	c.rw.Lock()
1018	defer c.rw.Unlock()
1019	cpy := c.nextBlock().copy()
1020	defer func() { c.revertIfErr(err, cpy) }()
1021	if c.addr == nil {
1022		return nil, eth.ErrAccountNil
1023	}
1024
1025	nextBlock := c.nextBlock()
1026	a := nextBlock.Auction
1027
1028	a.State.Coordinators[*c.addr] = &eth.Coordinator{
1029		Forger: forger,
1030		URL:    URL,
1031	}
1032
1033	a.Events.SetCoordinator = append(a.Events.SetCoordinator,
1034		eth.AuctionEventSetCoordinator{
1035			BidderAddress:  *c.addr,
1036			ForgerAddress:  forger,
1037			CoordinatorURL: URL,
1038		})
1039
1040	type data struct {
1041		BidderAddress ethCommon.Address
1042		ForgerAddress ethCommon.Address
1043		URL           string
1044	}
1045	return a.addTransaction(newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
1046}
1047
1048// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
1049func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
1050	c.rw.RLock()
1051	defer c.rw.RUnlock()
1052
1053	log.Error("TODO")
1054	return false, errTODO
1055}
1056
1057// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
1058func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
1059	c.rw.Lock()
1060	defer c.rw.Unlock()
1061	cpy := c.nextBlock().copy()
1062	defer func() { c.revertIfErr(err, cpy) }()
1063	if c.addr == nil {
1064		return nil, eth.ErrAccountNil
1065	}
1066
1067	log.Error("TODO")
1068	return nil, errTODO
1069}
1070
1071// AuctionGetSlotNumber is the interface to call the smart contract function
1072func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
1073	c.rw.RLock()
1074	defer c.rw.RUnlock()
1075
1076	currentBlock := c.currentBlock()
1077	a := currentBlock.Auction
1078	return a.getSlotNumber(blockNum), nil
1079}
1080
1081// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
1082func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
1083	c.rw.RLock()
1084	defer c.rw.RUnlock()
1085
1086	log.Error("TODO")
1087	return 0, errTODO
1088}
1089
1090// AuctionGetMinBidBySlot is the interface to call the smart contract function
1091func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
1092	c.rw.RLock()
1093	defer c.rw.RUnlock()
1094
1095	log.Error("TODO")
1096	return nil, errTODO
1097}
1098
1099// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
1100func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
1101	c.rw.RLock()
1102	defer c.rw.RUnlock()
1103
1104	log.Error("TODO")
1105	return nil, errTODO
1106}
1107
1108// AuctionGetSlotSet is the interface to call the smart contract function
1109func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
1110	c.rw.RLock()
1111	defer c.rw.RUnlock()
1112
1113	log.Error("TODO")
1114	return nil, errTODO
1115}
1116
1117// AuctionTokensReceived is the interface to call the smart contract function
1118// func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
1119// 	return errTODO
1120// }
1121
1122// AuctionBid is the interface to call the smart contract function
1123func (c *Client) AuctionBid(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
1124	c.rw.Lock()
1125	defer c.rw.Unlock()
1126	cpy := c.nextBlock().copy()
1127	defer func() { func() { c.revertIfErr(err, cpy) }() }()
1128	if c.addr == nil {
1129		return nil, eth.ErrAccountNil
1130	}
1131
1132	nextBlock := c.nextBlock()
1133	a := nextBlock.Auction
1134
1135	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
1136		return nil, errBidClosed
1137	}
1138
1139	if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
1140		return nil, errBidNotOpen
1141	}
1142
1143	minBid, err := a.getMinBidBySlot(slot)
1144	if err != nil {
1145		return nil, err
1146	}
1147	if bidAmount.Cmp(minBid) == -1 {
1148		return nil, errBidBelowMin
1149	}
1150
1151	if _, ok := a.State.Coordinators[*c.addr]; !ok {
1152		return nil, errCoordNotReg
1153	}
1154
1155	slotState, ok := a.State.Slots[slot]
1156	if !ok {
1157		slotState = eth.NewSlotState()
1158		a.State.Slots[slot] = slotState
1159	}
1160	slotState.Bidder = *c.addr
1161	slotState.BidAmount = bidAmount
1162
1163	a.Events.NewBid = append(a.Events.NewBid,
1164		eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
1165
1166	type data struct {
1167		Slot      int64
1168		BidAmount *big.Int
1169		Bidder    ethCommon.Address
1170	}
1171	return a.addTransaction(newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
1172}
1173
1174// AuctionMultiBid is the interface to call the smart contract function
1175func (c *Client) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int) (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// AuctionCanForge is the interface to call the smart contract function
1189func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
1190	c.rw.RLock()
1191	defer c.rw.RUnlock()
1192
1193	currentBlock := c.currentBlock()
1194	a := currentBlock.Auction
1195	return a.canForge(forger, blockNum)
1196}
1197
1198// AuctionForge is the interface to call the smart contract function
1199func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
1200	c.rw.Lock()
1201	defer c.rw.Unlock()
1202	cpy := c.nextBlock().copy()
1203	defer func() { c.revertIfErr(err, cpy) }()
1204	if c.addr == nil {
1205		return nil, eth.ErrAccountNil
1206	}
1207
1208	log.Error("TODO")
1209	return nil, errTODO
1210}
1211
1212// AuctionClaimHEZ is the interface to call the smart contract function
1213func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
1214	c.rw.Lock()
1215	defer c.rw.Unlock()
1216	cpy := c.nextBlock().copy()
1217	defer func() { c.revertIfErr(err, cpy) }()
1218	if c.addr == nil {
1219		return nil, eth.ErrAccountNil
1220	}
1221
1222	log.Error("TODO")
1223	return nil, errTODO
1224}
1225
1226// AuctionGetClaimableHEZ is the interface to call the smart contract function
1227func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
1228	c.rw.RLock()
1229	defer c.rw.RUnlock()
1230
1231	log.Error("TODO")
1232	return nil, errTODO
1233}
1234
1235// AuctionConstants returns the Constants of the Auction Smart Contract
1236func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
1237	c.rw.RLock()
1238	defer c.rw.RUnlock()
1239
1240	return c.auctionConstants, nil
1241}
1242
1243// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
1244func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
1245	c.rw.RLock()
1246	defer c.rw.RUnlock()
1247
1248	block, ok := c.blocks[blockNum]
1249	if !ok {
1250		return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
1251	}
1252	return &block.Auction.Events, &block.Eth.Hash, nil
1253}