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