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// RollupL1UserTxERC20Permit is the interface to call the smart contract function
 625func (c *Client) RollupL1UserTxERC20Permit(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64, deadline *big.Int) (tx *types.Transaction, err error) {
 626	log.Error("TODO")
 627	return nil, errTODO
 628}
 629
 630// RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
 631func (c *Client) RollupL1UserTxERC20ETH(
 632	fromBJJ *babyjub.PublicKey,
 633	fromIdx int64,
 634	loadAmount *big.Int,
 635	amount *big.Int,
 636	tokenID uint32,
 637	toIdx int64,
 638) (tx *types.Transaction, err error) {
 639	c.rw.Lock()
 640	defer c.rw.Unlock()
 641	cpy := c.nextBlock().copy()
 642	defer func() { c.revertIfErr(err, cpy) }()
 643
 644	_, err = common.NewFloat16(amount)
 645	if err != nil {
 646		return nil, err
 647	}
 648	_, err = common.NewFloat16(loadAmount)
 649	if err != nil {
 650		return nil, err
 651	}
 652
 653	nextBlock := c.nextBlock()
 654	r := nextBlock.Rollup
 655	queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 656	if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
 657		r.State.LastToForgeL1TxsNum++
 658		r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 659		queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 660	}
 661	if fromIdx > r.State.CurrentIdx {
 662		panic("l1Tx.FromIdx > r.State.CurrentIdx")
 663	}
 664	if int(tokenID)+1 > len(r.State.TokenList) {
 665		panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
 666	}
 667	toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
 668	l1Tx, err := common.NewL1Tx(&common.L1Tx{
 669		FromIdx:         common.Idx(fromIdx),
 670		FromEthAddr:     *c.addr,
 671		FromBJJ:         fromBJJ,
 672		Amount:          amount,
 673		LoadAmount:      loadAmount,
 674		TokenID:         common.TokenID(tokenID),
 675		ToIdx:           common.Idx(toIdx),
 676		ToForgeL1TxsNum: &toForgeL1TxsNum,
 677		Position:        len(queue.L1TxQueue),
 678		UserOrigin:      true,
 679	})
 680	if err != nil {
 681		return nil, err
 682	}
 683
 684	queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
 685	r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
 686		L1UserTx: *l1Tx,
 687	})
 688	return r.addTransaction(newTransaction("l1UserTxERC20ETH", l1Tx)), nil
 689}
 690
 691// RollupL1UserTxERC777 is the interface to call the smart contract function
 692// func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
 693// 	log.Error("TODO")
 694// 	return nil, errTODO
 695// }
 696
 697// RollupRegisterTokensCount is the interface to call the smart contract function
 698func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
 699	log.Error("TODO")
 700	return nil, errTODO
 701}
 702
 703// RollupWithdrawCircuit is the interface to call the smart contract function
 704func (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) {
 705	log.Error("TODO")
 706	return nil, errTODO
 707}
 708
 709// RollupWithdrawMerkleProof is the interface to call the smart contract function
 710func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction, error) {
 711	log.Error("TODO")
 712	return nil, errTODO
 713}
 714
 715type transactionData struct {
 716	Name  string
 717	Value interface{}
 718}
 719
 720func newTransaction(name string, value interface{}) *types.Transaction {
 721	data, err := json.Marshal(transactionData{name, value})
 722	if err != nil {
 723		panic(err)
 724	}
 725	return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
 726		data)
 727}
 728
 729// RollupForgeBatch is the interface to call the smart contract function
 730func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (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	a := c.nextBlock().Auction
 740	ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
 741	if err != nil {
 742		return nil, err
 743	}
 744	if !ok {
 745		return nil, fmt.Errorf("incorrect slot")
 746	}
 747
 748	// TODO: Verify proof
 749
 750	// Auction
 751	err = a.forge(*c.addr)
 752	if err != nil {
 753		return nil, err
 754	}
 755
 756	// TODO: If successful, store the tx in a successful array.
 757	// TODO: If failed, store the tx in a failed array.
 758	// TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
 759
 760	return c.addBatch(args)
 761}
 762
 763// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
 764func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
 765	c.rw.Lock()
 766	defer c.rw.Unlock()
 767
 768	if _, err := c.addBatch(args); err != nil {
 769		panic(err)
 770	}
 771}
 772
 773func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
 774	nextBlock := c.nextBlock()
 775	r := nextBlock.Rollup
 776	r.State.StateRoot = args.NewStRoot
 777	if args.NewLastIdx < r.State.CurrentIdx {
 778		return nil, fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx")
 779	}
 780	r.State.CurrentIdx = args.NewLastIdx
 781	r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
 782	if args.L1Batch {
 783		r.State.CurrentToForgeL1TxsNum++
 784		if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
 785			r.State.LastToForgeL1TxsNum++
 786			r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 787		}
 788	}
 789	ethTx := r.addTransaction(newTransaction("forgebatch", args))
 790	c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
 791	r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
 792		BatchNum:  int64(len(r.State.ExitRoots)),
 793		EthTxHash: ethTx.Hash(),
 794	})
 795
 796	return ethTx, nil
 797}
 798
 799// RollupAddTokenSimple is a wrapper around RollupAddToken that automatically
 800// sets `deadlie`.
 801func (c *Client) RollupAddTokenSimple(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
 802	return c.RollupAddToken(tokenAddress, feeAddToken, big.NewInt(9999)) //nolint:gomnd
 803}
 804
 805// RollupAddToken is the interface to call the smart contract function
 806func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int,
 807	deadline *big.Int) (tx *types.Transaction, err error) {
 808	c.rw.Lock()
 809	defer c.rw.Unlock()
 810	cpy := c.nextBlock().copy()
 811	defer func() { c.revertIfErr(err, cpy) }()
 812	if c.addr == nil {
 813		return nil, eth.ErrAccountNil
 814	}
 815
 816	nextBlock := c.nextBlock()
 817	r := nextBlock.Rollup
 818	if _, ok := r.State.TokenMap[tokenAddress]; ok {
 819		return nil, fmt.Errorf("Token %v already registered", tokenAddress)
 820	}
 821	if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
 822		return nil, fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken)
 823	}
 824
 825	r.State.TokenMap[tokenAddress] = true
 826	r.State.TokenList = append(r.State.TokenList, tokenAddress)
 827	r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
 828		TokenID: uint32(len(r.State.TokenList) - 1)})
 829	return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
 830}
 831
 832// RollupGetCurrentTokens is the interface to call the smart contract function
 833func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
 834	c.rw.RLock()
 835	defer c.rw.RUnlock()
 836
 837	log.Error("TODO")
 838	return nil, errTODO
 839}
 840
 841// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
 842func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
 843	c.rw.Lock()
 844	defer c.rw.Unlock()
 845	cpy := c.nextBlock().copy()
 846	defer func() { c.revertIfErr(err, cpy) }()
 847	if c.addr == nil {
 848		return nil, eth.ErrAccountNil
 849	}
 850
 851	log.Error("TODO")
 852	return nil, errTODO
 853}
 854
 855// RollupUpdateFeeAddToken is the interface to call the smart contract function
 856func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
 857	c.rw.Lock()
 858	defer c.rw.Unlock()
 859	cpy := c.nextBlock().copy()
 860	defer func() { c.revertIfErr(err, cpy) }()
 861	if c.addr == nil {
 862		return nil, eth.ErrAccountNil
 863	}
 864
 865	log.Error("TODO")
 866	return nil, errTODO
 867}
 868
 869// RollupUpdateTokensHEZ is the interface to call the smart contract function
 870// func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
 871// 	c.rw.Lock()
 872// 	defer c.rw.Unlock()
 873// 	cpy := c.nextBlock().copy()
 874// 	defer func() { c.revertIfErr(err, cpy) }()
 875//
 876// 	log.Error("TODO")
 877// 	return nil, errTODO
 878// }
 879
 880// RollupUpdateGovernance is the interface to call the smart contract function
 881// func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
 882// 	return nil, errTODO
 883// }
 884
 885// RollupConstants returns the Constants of the Rollup Smart Contract
 886func (c *Client) RollupConstants() (*eth.RollupPublicConstants, error) {
 887	c.rw.RLock()
 888	defer c.rw.RUnlock()
 889
 890	log.Error("TODO")
 891	return nil, errTODO
 892}
 893
 894// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
 895func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
 896	c.rw.RLock()
 897	defer c.rw.RUnlock()
 898
 899	block, ok := c.blocks[blockNum]
 900	if !ok {
 901		return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
 902	}
 903	return &block.Rollup.Events, &block.Eth.Hash, nil
 904}
 905
 906// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
 907func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
 908	c.rw.RLock()
 909	defer c.rw.RUnlock()
 910
 911	batch, ok := c.forgeBatchArgs[ethTxHash]
 912	if !ok {
 913		return nil, nil, fmt.Errorf("transaction not found")
 914	}
 915	return &batch.ForgeBatchArgs, &batch.Sender, nil
 916}
 917
 918//
 919// Auction
 920//
 921
 922// AuctionSetSlotDeadline is the interface to call the smart contract function
 923func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
 924	c.rw.Lock()
 925	defer c.rw.Unlock()
 926	cpy := c.nextBlock().copy()
 927	defer func() { c.revertIfErr(err, cpy) }()
 928	if c.addr == nil {
 929		return nil, eth.ErrAccountNil
 930	}
 931
 932	log.Error("TODO")
 933	return nil, errTODO
 934}
 935
 936// AuctionGetSlotDeadline is the interface to call the smart contract function
 937func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
 938	c.rw.RLock()
 939	defer c.rw.RUnlock()
 940
 941	log.Error("TODO")
 942	return 0, errTODO
 943}
 944
 945// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
 946func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
 947	c.rw.Lock()
 948	defer c.rw.Unlock()
 949	cpy := c.nextBlock().copy()
 950	defer func() { c.revertIfErr(err, cpy) }()
 951	if c.addr == nil {
 952		return nil, eth.ErrAccountNil
 953	}
 954
 955	log.Error("TODO")
 956	return nil, errTODO
 957}
 958
 959// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
 960func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
 961	c.rw.RLock()
 962	defer c.rw.RUnlock()
 963
 964	log.Error("TODO")
 965	return 0, errTODO
 966}
 967
 968// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
 969func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
 970	c.rw.Lock()
 971	defer c.rw.Unlock()
 972	cpy := c.nextBlock().copy()
 973	defer func() { c.revertIfErr(err, cpy) }()
 974	if c.addr == nil {
 975		return nil, eth.ErrAccountNil
 976	}
 977
 978	log.Error("TODO")
 979	return nil, errTODO
 980}
 981
 982// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
 983func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
 984	c.rw.RLock()
 985	defer c.rw.RUnlock()
 986
 987	log.Error("TODO")
 988	return 0, errTODO
 989}
 990
 991// AuctionSetOutbidding is the interface to call the smart contract function
 992func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
 993	c.rw.Lock()
 994	defer c.rw.Unlock()
 995	cpy := c.nextBlock().copy()
 996	defer func() { c.revertIfErr(err, cpy) }()
 997	if c.addr == nil {
 998		return nil, eth.ErrAccountNil
 999	}
1000
1001	log.Error("TODO")
1002	return nil, errTODO
1003}
1004
1005// AuctionGetOutbidding is the interface to call the smart contract function
1006func (c *Client) AuctionGetOutbidding() (uint16, error) {
1007	c.rw.RLock()
1008	defer c.rw.RUnlock()
1009
1010	log.Error("TODO")
1011	return 0, errTODO
1012}
1013
1014// AuctionSetAllocationRatio is the interface to call the smart contract function
1015func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
1016	c.rw.Lock()
1017	defer c.rw.Unlock()
1018	cpy := c.nextBlock().copy()
1019	defer func() { c.revertIfErr(err, cpy) }()
1020	if c.addr == nil {
1021		return nil, eth.ErrAccountNil
1022	}
1023
1024	log.Error("TODO")
1025	return nil, errTODO
1026}
1027
1028// AuctionGetAllocationRatio is the interface to call the smart contract function
1029func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
1030	c.rw.RLock()
1031	defer c.rw.RUnlock()
1032
1033	log.Error("TODO")
1034	return [3]uint16{}, errTODO
1035}
1036
1037// AuctionSetDonationAddress is the interface to call the smart contract function
1038func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
1039	c.rw.Lock()
1040	defer c.rw.Unlock()
1041	cpy := c.nextBlock().copy()
1042	defer func() { c.revertIfErr(err, cpy) }()
1043	if c.addr == nil {
1044		return nil, eth.ErrAccountNil
1045	}
1046
1047	log.Error("TODO")
1048	return nil, errTODO
1049}
1050
1051// AuctionGetDonationAddress is the interface to call the smart contract function
1052func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
1053	c.rw.RLock()
1054	defer c.rw.RUnlock()
1055
1056	log.Error("TODO")
1057	return nil, errTODO
1058}
1059
1060// AuctionSetBootCoordinator is the interface to call the smart contract function
1061func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
1062	c.rw.Lock()
1063	defer c.rw.Unlock()
1064	cpy := c.nextBlock().copy()
1065	defer func() { c.revertIfErr(err, cpy) }()
1066	if c.addr == nil {
1067		return nil, eth.ErrAccountNil
1068	}
1069
1070	log.Error("TODO")
1071	return nil, errTODO
1072}
1073
1074// AuctionGetBootCoordinator is the interface to call the smart contract function
1075func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
1076	c.rw.RLock()
1077	defer c.rw.RUnlock()
1078
1079	currentBlock := c.currentBlock()
1080	a := currentBlock.Auction
1081
1082	return &a.Vars.BootCoordinator, nil
1083}
1084
1085// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
1086func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
1087	c.rw.Lock()
1088	defer c.rw.Unlock()
1089	cpy := c.nextBlock().copy()
1090	defer func() { c.revertIfErr(err, cpy) }()
1091	if c.addr == nil {
1092		return nil, eth.ErrAccountNil
1093	}
1094
1095	log.Error("TODO")
1096	return nil, errTODO
1097}
1098
1099// AuctionSetCoordinator is the interface to call the smart contract function
1100func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
1101	c.rw.Lock()
1102	defer c.rw.Unlock()
1103	cpy := c.nextBlock().copy()
1104	defer func() { c.revertIfErr(err, cpy) }()
1105	if c.addr == nil {
1106		return nil, eth.ErrAccountNil
1107	}
1108
1109	nextBlock := c.nextBlock()
1110	a := nextBlock.Auction
1111
1112	a.State.Coordinators[*c.addr] = &eth.Coordinator{
1113		Forger: forger,
1114		URL:    URL,
1115	}
1116
1117	a.Events.SetCoordinator = append(a.Events.SetCoordinator,
1118		eth.AuctionEventSetCoordinator{
1119			BidderAddress:  *c.addr,
1120			ForgerAddress:  forger,
1121			CoordinatorURL: URL,
1122		})
1123
1124	type data struct {
1125		BidderAddress ethCommon.Address
1126		ForgerAddress ethCommon.Address
1127		URL           string
1128	}
1129	return a.addTransaction(newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
1130}
1131
1132// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
1133func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
1134	c.rw.RLock()
1135	defer c.rw.RUnlock()
1136
1137	log.Error("TODO")
1138	return false, errTODO
1139}
1140
1141// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
1142func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
1143	c.rw.Lock()
1144	defer c.rw.Unlock()
1145	cpy := c.nextBlock().copy()
1146	defer func() { c.revertIfErr(err, cpy) }()
1147	if c.addr == nil {
1148		return nil, eth.ErrAccountNil
1149	}
1150
1151	log.Error("TODO")
1152	return nil, errTODO
1153}
1154
1155// AuctionGetSlotNumber is the interface to call the smart contract function
1156func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
1157	c.rw.RLock()
1158	defer c.rw.RUnlock()
1159
1160	currentBlock := c.currentBlock()
1161	a := currentBlock.Auction
1162	return a.getSlotNumber(blockNum), nil
1163}
1164
1165// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
1166func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
1167	c.rw.RLock()
1168	defer c.rw.RUnlock()
1169
1170	log.Error("TODO")
1171	return 0, errTODO
1172}
1173
1174// AuctionGetMinBidBySlot is the interface to call the smart contract function
1175func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
1176	c.rw.RLock()
1177	defer c.rw.RUnlock()
1178
1179	log.Error("TODO")
1180	return nil, errTODO
1181}
1182
1183// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
1184func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
1185	c.rw.RLock()
1186	defer c.rw.RUnlock()
1187
1188	log.Error("TODO")
1189	return nil, errTODO
1190}
1191
1192// AuctionGetSlotSet is the interface to call the smart contract function
1193func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
1194	c.rw.RLock()
1195	defer c.rw.RUnlock()
1196
1197	log.Error("TODO")
1198	return nil, errTODO
1199}
1200
1201// AuctionTokensReceived is the interface to call the smart contract function
1202// func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
1203// 	return errTODO
1204// }
1205
1206// AuctionBidSimple is a wrapper around AuctionBid that automatically sets `amount` and `deadline`.
1207func (c *Client) AuctionBidSimple(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
1208	return c.AuctionBid(bidAmount, slot, bidAmount, big.NewInt(99999)) //nolint:gomnd
1209}
1210
1211// AuctionBid is the interface to call the smart contract function.  This
1212// implementation behaves as if any address has infinite tokens.
1213func (c *Client) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
1214	deadline *big.Int) (tx *types.Transaction, err error) {
1215	c.rw.Lock()
1216	defer c.rw.Unlock()
1217	cpy := c.nextBlock().copy()
1218	defer func() { func() { c.revertIfErr(err, cpy) }() }()
1219	if c.addr == nil {
1220		return nil, eth.ErrAccountNil
1221	}
1222
1223	nextBlock := c.nextBlock()
1224	a := nextBlock.Auction
1225
1226	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
1227		return nil, errBidClosed
1228	}
1229
1230	if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
1231		return nil, errBidNotOpen
1232	}
1233
1234	minBid, err := a.getMinBidBySlot(slot)
1235	if err != nil {
1236		return nil, err
1237	}
1238	if bidAmount.Cmp(minBid) == -1 {
1239		return nil, errBidBelowMin
1240	}
1241
1242	if _, ok := a.State.Coordinators[*c.addr]; !ok {
1243		return nil, errCoordNotReg
1244	}
1245
1246	slotState, ok := a.State.Slots[slot]
1247	if !ok {
1248		slotState = eth.NewSlotState()
1249		a.State.Slots[slot] = slotState
1250	}
1251	slotState.Bidder = *c.addr
1252	slotState.BidAmount = bidAmount
1253
1254	a.Events.NewBid = append(a.Events.NewBid,
1255		eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
1256
1257	type data struct {
1258		Slot      int64
1259		BidAmount *big.Int
1260		Bidder    ethCommon.Address
1261	}
1262	return a.addTransaction(newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
1263}
1264
1265// AuctionMultiBid is the interface to call the smart contract function.  This
1266// implementation behaves as if any address has infinite tokens.
1267func (c *Client) AuctionMultiBid(amount *big.Int, startingSlot int64, endingSlot int64, slotSet [6]bool,
1268	maxBid, closedMinBid, deadline *big.Int) (tx *types.Transaction, err error) {
1269	c.rw.Lock()
1270	defer c.rw.Unlock()
1271	cpy := c.nextBlock().copy()
1272	defer func() { c.revertIfErr(err, cpy) }()
1273	if c.addr == nil {
1274		return nil, eth.ErrAccountNil
1275	}
1276
1277	log.Error("TODO")
1278	return nil, errTODO
1279}
1280
1281// AuctionCanForge is the interface to call the smart contract function
1282func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
1283	c.rw.RLock()
1284	defer c.rw.RUnlock()
1285
1286	currentBlock := c.currentBlock()
1287	a := currentBlock.Auction
1288	return a.canForge(forger, blockNum)
1289}
1290
1291// AuctionForge is the interface to call the smart contract function
1292func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
1293	c.rw.Lock()
1294	defer c.rw.Unlock()
1295	cpy := c.nextBlock().copy()
1296	defer func() { c.revertIfErr(err, cpy) }()
1297	if c.addr == nil {
1298		return nil, eth.ErrAccountNil
1299	}
1300
1301	log.Error("TODO")
1302	return nil, errTODO
1303}
1304
1305// AuctionClaimHEZ is the interface to call the smart contract function
1306func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
1307	c.rw.Lock()
1308	defer c.rw.Unlock()
1309	cpy := c.nextBlock().copy()
1310	defer func() { c.revertIfErr(err, cpy) }()
1311	if c.addr == nil {
1312		return nil, eth.ErrAccountNil
1313	}
1314
1315	log.Error("TODO")
1316	return nil, errTODO
1317}
1318
1319// AuctionGetClaimableHEZ is the interface to call the smart contract function
1320func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
1321	c.rw.RLock()
1322	defer c.rw.RUnlock()
1323
1324	log.Error("TODO")
1325	return nil, errTODO
1326}
1327
1328// AuctionConstants returns the Constants of the Auction Smart Contract
1329func (c *Client) AuctionConstants() (*eth.AuctionConstants, error) {
1330	c.rw.RLock()
1331	defer c.rw.RUnlock()
1332
1333	return c.auctionConstants, nil
1334}
1335
1336// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
1337func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
1338	c.rw.RLock()
1339	defer c.rw.RUnlock()
1340
1341	block, ok := c.blocks[blockNum]
1342	if !ok {
1343		return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
1344	}
1345	return &block.Auction.Events, &block.Eth.Hash, nil
1346}