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