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