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