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/hermeznetwork/tracerr"
  20	"github.com/iden3/go-iden3-crypto/babyjub"
  21	"github.com/mitchellh/copystructure"
  22)
  23
  24func init() {
  25	copystructure.Copiers[reflect.TypeOf(big.Int{})] =
  26		func(raw interface{}) (interface{}, error) {
  27			in := raw.(big.Int)
  28			out := new(big.Int).Set(&in)
  29			return *out, nil
  30		}
  31}
  32
  33// WDelayerBlock stores all the data related to the WDelayer SC from an ethereum block
  34type WDelayerBlock struct {
  35	// State     eth.WDelayerState // TODO
  36	Vars      common.WDelayerVariables
  37	Events    eth.WDelayerEvents
  38	Txs       map[ethCommon.Hash]*types.Transaction
  39	Constants *common.WDelayerConstants
  40	Eth       *EthereumBlock
  41}
  42
  43func (w *WDelayerBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  44	txHash := tx.Hash()
  45	w.Txs[txHash] = tx
  46	return tx
  47}
  48
  49func (w *WDelayerBlock) deposit(txHash ethCommon.Hash, owner, token ethCommon.Address, amount *big.Int) {
  50	w.Events.Deposit = append(w.Events.Deposit, eth.WDelayerEventDeposit{
  51		Owner:            owner,
  52		Token:            token,
  53		Amount:           amount,
  54		DepositTimestamp: uint64(w.Eth.Time),
  55		TxHash:           txHash,
  56	})
  57}
  58
  59// RollupBlock stores all the data related to the Rollup SC from an ethereum block
  60type RollupBlock struct {
  61	State     eth.RollupState
  62	Vars      common.RollupVariables
  63	Events    eth.RollupEvents
  64	Txs       map[ethCommon.Hash]*types.Transaction
  65	Constants *common.RollupConstants
  66	Eth       *EthereumBlock
  67}
  68
  69func (r *RollupBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  70	txHash := tx.Hash()
  71	r.Txs[txHash] = tx
  72	return tx
  73}
  74
  75var (
  76	errBidClosed   = fmt.Errorf("Bid has already been closed")
  77	errBidNotOpen  = fmt.Errorf("Bid has not been opened yet")
  78	errBidBelowMin = fmt.Errorf("Bid below minimum")
  79	errCoordNotReg = fmt.Errorf("Coordinator not registered")
  80)
  81
  82// AuctionBlock stores all the data related to the Auction SC from an ethereum block
  83type AuctionBlock struct {
  84	State     eth.AuctionState
  85	Vars      common.AuctionVariables
  86	Events    eth.AuctionEvents
  87	Txs       map[ethCommon.Hash]*types.Transaction
  88	Constants *common.AuctionConstants
  89	Eth       *EthereumBlock
  90}
  91
  92func (a *AuctionBlock) addTransaction(tx *types.Transaction) *types.Transaction {
  93	txHash := tx.Hash()
  94	a.Txs[txHash] = tx
  95	return tx
  96}
  97
  98func (a *AuctionBlock) getSlotNumber(blockNumber int64) int64 {
  99	if a.Eth.BlockNum >= a.Constants.GenesisBlockNum {
 100		return (blockNumber - a.Constants.GenesisBlockNum) / int64(a.Constants.BlocksPerSlot)
 101	}
 102	return 0
 103}
 104
 105func (a *AuctionBlock) getCurrentSlotNumber() int64 {
 106	return a.getSlotNumber(a.Eth.BlockNum)
 107}
 108
 109func (a *AuctionBlock) getSlotSet(slot int64) int64 {
 110	return slot % int64(len(a.Vars.DefaultSlotSetBid))
 111}
 112
 113func (a *AuctionBlock) getMinBidBySlot(slot int64) (*big.Int, error) {
 114	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
 115		return nil, tracerr.Wrap(errBidClosed)
 116	}
 117
 118	slotSet := a.getSlotSet(slot)
 119	// fmt.Println("slot:", slot, "slotSet:", slotSet)
 120	var prevBid *big.Int
 121	slotState, ok := a.State.Slots[slot]
 122	if !ok {
 123		slotState = eth.NewSlotState()
 124		a.State.Slots[slot] = slotState
 125	}
 126	// If the bidAmount for a slot is 0 it means that it has not yet been bid, so the midBid will be the minimum
 127	// bid for the slot time plus the outbidding set, otherwise it will be the bidAmount plus the outbidding
 128	if slotState.BidAmount.Cmp(big.NewInt(0)) == 0 {
 129		prevBid = a.Vars.DefaultSlotSetBid[slotSet]
 130	} else {
 131		prevBid = slotState.BidAmount
 132	}
 133	outBid := new(big.Int).Set(prevBid)
 134	// fmt.Println("outBid:", outBid)
 135	outBid.Mul(outBid, big.NewInt(int64(a.Vars.Outbidding)))
 136	outBid.Div(outBid, big.NewInt(10000)) //nolint:gomnd
 137	outBid.Add(prevBid, outBid)
 138	// fmt.Println("minBid:", outBid)
 139	return outBid, nil
 140}
 141
 142func (a *AuctionBlock) forge(forger ethCommon.Address) error {
 143	if ok, err := a.canForge(forger, a.Eth.BlockNum); err != nil {
 144		return tracerr.Wrap(err)
 145	} else if !ok {
 146		return tracerr.Wrap(fmt.Errorf("Can't forge"))
 147	}
 148
 149	slotToForge := a.getSlotNumber(a.Eth.BlockNum)
 150	slotState, ok := a.State.Slots[slotToForge]
 151	if !ok {
 152		slotState = eth.NewSlotState()
 153		a.State.Slots[slotToForge] = slotState
 154	}
 155	slotState.Fulfilled = true
 156
 157	a.Events.NewForge = append(a.Events.NewForge, eth.AuctionEventNewForge{
 158		Forger:      forger,
 159		SlotToForge: slotToForge,
 160	})
 161	return nil
 162}
 163
 164func (a *AuctionBlock) canForge(forger ethCommon.Address, blockNum int64) (bool, error) {
 165	if blockNum < a.Constants.GenesisBlockNum {
 166		return false, tracerr.Wrap(fmt.Errorf("Auction has not started yet"))
 167	}
 168
 169	slotToForge := a.getSlotNumber(blockNum)
 170	// fmt.Printf("DBG canForge slot: %v\n", slotToForge)
 171	// Get the relativeBlock to check if the slotDeadline has been exceeded
 172	relativeBlock := blockNum - (a.Constants.GenesisBlockNum + (slotToForge * int64(a.Constants.BlocksPerSlot)))
 173
 174	// If the closedMinBid is 0 it means that we have to take as minBid the one that is set for this slot set,
 175	// otherwise the one that has been saved will be used
 176	var minBid *big.Int
 177	slotState, ok := a.State.Slots[slotToForge]
 178	if !ok {
 179		slotState = eth.NewSlotState()
 180		a.State.Slots[slotToForge] = slotState
 181	}
 182	if slotState.ClosedMinBid.Cmp(big.NewInt(0)) == 0 {
 183		minBid = a.Vars.DefaultSlotSetBid[a.getSlotSet(slotToForge)]
 184	} else {
 185		minBid = slotState.ClosedMinBid
 186	}
 187
 188	if !slotState.Fulfilled && (relativeBlock >= int64(a.Vars.SlotDeadline)) {
 189		// if the relative block has exceeded the slotDeadline and no batch has been forged, anyone can forge
 190		return true, nil
 191		// TODO, find the forger set by the Bidder
 192	} else if coord, ok := a.State.Coordinators[slotState.Bidder]; ok &&
 193		coord.Forger == forger && slotState.BidAmount.Cmp(minBid) >= 0 {
 194		// if forger bidAmount has exceeded the minBid it can forge
 195		return true, nil
 196	} else if a.Vars.BootCoordinator == forger && slotState.BidAmount.Cmp(minBid) == -1 {
 197		// if it's the boot coordinator and it has not been bid or the bid is below the minimum it can forge
 198		return true, nil
 199	} else {
 200		return false, nil
 201	}
 202}
 203
 204// EthereumBlock stores all the generic data related to the an ethereum block
 205type EthereumBlock struct {
 206	BlockNum   int64
 207	Time       int64
 208	Hash       ethCommon.Hash
 209	ParentHash ethCommon.Hash
 210	Tokens     map[ethCommon.Address]eth.ERC20Consts
 211	// state      ethState
 212}
 213
 214// Block represents a ethereum block
 215type Block struct {
 216	Rollup   *RollupBlock
 217	Auction  *AuctionBlock
 218	WDelayer *WDelayerBlock
 219	Eth      *EthereumBlock
 220}
 221
 222func (b *Block) copy() *Block {
 223	bCopyRaw, err := copystructure.Copy(b)
 224	if err != nil {
 225		panic(err)
 226	}
 227	bCopy := bCopyRaw.(*Block)
 228	return bCopy
 229}
 230
 231// Next prepares the successive block.
 232func (b *Block) Next() *Block {
 233	blockNext := b.copy()
 234	blockNext.Rollup.Events = eth.NewRollupEvents()
 235	blockNext.Auction.Events = eth.NewAuctionEvents()
 236
 237	blockNext.Eth.BlockNum = b.Eth.BlockNum + 1
 238	blockNext.Eth.ParentHash = b.Eth.Hash
 239
 240	blockNext.Rollup.Constants = b.Rollup.Constants
 241	blockNext.Auction.Constants = b.Auction.Constants
 242	blockNext.WDelayer.Constants = b.WDelayer.Constants
 243	blockNext.Rollup.Eth = blockNext.Eth
 244	blockNext.Auction.Eth = blockNext.Eth
 245	blockNext.WDelayer.Eth = blockNext.Eth
 246
 247	return blockNext
 248}
 249
 250// ClientSetup is used to initialize the constants of the Smart Contracts and
 251// other details of the test Client
 252type ClientSetup struct {
 253	RollupConstants   *common.RollupConstants
 254	RollupVariables   *common.RollupVariables
 255	AuctionConstants  *common.AuctionConstants
 256	AuctionVariables  *common.AuctionVariables
 257	WDelayerConstants *common.WDelayerConstants
 258	WDelayerVariables *common.WDelayerVariables
 259	VerifyProof       bool
 260}
 261
 262// NewClientSetupExample returns a ClientSetup example with hardcoded realistic
 263// values.  With this setup, the rollup genesis will be block 1, and block 0
 264// and 1 will be premined.
 265//nolint:gomnd
 266func NewClientSetupExample() *ClientSetup {
 267	// rfield, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
 268	// if !ok {
 269	// 	panic("bad rfield")
 270	// }
 271	initialMinimalBidding, ok := new(big.Int).SetString("10000000000000000000", 10) // 10 * (1e18)
 272	if !ok {
 273		panic("bad initialMinimalBidding")
 274	}
 275	tokenHEZ := ethCommon.HexToAddress("0x51D243D62852Bba334DD5cc33f242BAc8c698074")
 276	governanceAddress := ethCommon.HexToAddress("0x688EfD95BA4391f93717CF02A9aED9DBD2855cDd")
 277	rollupConstants := &common.RollupConstants{
 278		Verifiers: []common.RollupVerifierStruct{
 279			{
 280				MaxTx:   2048,
 281				NLevels: 32,
 282			},
 283		},
 284		TokenHEZ:                   tokenHEZ,
 285		HermezGovernanceDAOAddress: governanceAddress,
 286		SafetyAddress:              ethCommon.HexToAddress("0x84d8B79E84fe87B14ad61A554e740f6736bF4c20"),
 287		HermezAuctionContract:      ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
 288		WithdrawDelayerContract:    ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
 289	}
 290	rollupVariables := &common.RollupVariables{
 291		FeeAddToken:           big.NewInt(11),
 292		ForgeL1L2BatchTimeout: 9,
 293		WithdrawalDelay:       80,
 294	}
 295	auctionConstants := &common.AuctionConstants{
 296		BlocksPerSlot:         40,
 297		InitialMinimalBidding: initialMinimalBidding,
 298		GenesisBlockNum:       1,
 299		GovernanceAddress:     governanceAddress,
 300		TokenHEZ:              tokenHEZ,
 301		HermezRollup:          ethCommon.HexToAddress("0x474B6e29852257491cf283EfB1A9C61eBFe48369"),
 302	}
 303	auctionVariables := &common.AuctionVariables{
 304		DonationAddress: ethCommon.HexToAddress("0x61Ed87CF0A1496b49A420DA6D84B58196b98f2e7"),
 305		BootCoordinator: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 306		DefaultSlotSetBid: [6]*big.Int{
 307			big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
 308			big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)},
 309		ClosedAuctionSlots: 2,
 310		OpenAuctionSlots:   4320,
 311		AllocationRatio:    [3]uint16{4000, 4000, 2000},
 312		Outbidding:         1000,
 313		SlotDeadline:       20,
 314	}
 315	wDelayerConstants := &common.WDelayerConstants{
 316		MaxWithdrawalDelay:   60 * 60 * 24 * 7 * 2,  // 2 weeks
 317		MaxEmergencyModeTime: 60 * 60 * 24 * 7 * 26, // 26 weeks
 318		HermezRollup:         auctionConstants.HermezRollup,
 319	}
 320	wDelayerVariables := &common.WDelayerVariables{
 321		HermezGovernanceDAOAddress: ethCommon.HexToAddress("0xcfD0d163AE6432a72682323E2C3A5a69e6B37D12"),
 322		WhiteHackGroupAddress:      ethCommon.HexToAddress("0x2730700932a4FDB97B9268A3Ca29f97Ea5fd7EA0"),
 323		HermezKeeperAddress:        ethCommon.HexToAddress("0x92aAD86176dC0f0046FE85Ed5dA008a828bE3868"),
 324		WithdrawalDelay:            60,
 325		EmergencyModeStartingTime:  0,
 326		EmergencyMode:              false,
 327	}
 328	return &ClientSetup{
 329		RollupConstants:   rollupConstants,
 330		RollupVariables:   rollupVariables,
 331		AuctionConstants:  auctionConstants,
 332		AuctionVariables:  auctionVariables,
 333		WDelayerConstants: wDelayerConstants,
 334		WDelayerVariables: wDelayerVariables,
 335	}
 336}
 337
 338// Timer is an interface to simulate a source of time, useful to advance time
 339// virtually.
 340type Timer interface {
 341	Time() int64
 342}
 343
 344// type forgeBatchArgs struct {
 345// 	ethTx     *types.Transaction
 346// 	blockNum  int64
 347// 	blockHash ethCommon.Hash
 348// }
 349
 350type batch struct {
 351	ForgeBatchArgs eth.RollupForgeBatchArgs
 352	Sender         ethCommon.Address
 353}
 354
 355// Client implements the eth.ClientInterface interface, allowing to manipulate the
 356// values for testing, working with deterministic results.
 357type Client struct {
 358	rw                *sync.RWMutex
 359	log               bool
 360	addr              *ethCommon.Address
 361	rollupConstants   *common.RollupConstants
 362	auctionConstants  *common.AuctionConstants
 363	wDelayerConstants *common.WDelayerConstants
 364	blocks            map[int64]*Block
 365	// state            state
 366	blockNum    int64 // last mined block num
 367	maxBlockNum int64 // highest block num calculated
 368	timer       Timer
 369	hasher      hasher
 370
 371	forgeBatchArgsPending map[ethCommon.Hash]*batch
 372	forgeBatchArgs        map[ethCommon.Hash]*batch
 373}
 374
 375// NewClient returns a new test Client that implements the eth.IClient
 376// interface, at the given initialBlockNumber.
 377func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
 378	blocks := make(map[int64]*Block)
 379	blockNum := int64(0)
 380
 381	hasher := hasher{}
 382	// Add ethereum genesis block
 383	mapL1TxQueue := make(map[int64]*eth.QueueStruct)
 384	mapL1TxQueue[0] = eth.NewQueueStruct()
 385	mapL1TxQueue[1] = eth.NewQueueStruct()
 386	blockCurrent := &Block{
 387		Rollup: &RollupBlock{
 388			State: eth.RollupState{
 389				StateRoot:        big.NewInt(0),
 390				ExitRoots:        make([]*big.Int, 1),
 391				ExitNullifierMap: make(map[int64]map[int64]bool),
 392				// TokenID = 0 is ETH.  Set first entry in TokenList with 0x0 address for ETH.
 393				TokenList:              []ethCommon.Address{{}},
 394				TokenMap:               make(map[ethCommon.Address]bool),
 395				MapL1TxQueue:           mapL1TxQueue,
 396				LastL1L2Batch:          0,
 397				CurrentToForgeL1TxsNum: 0,
 398				LastToForgeL1TxsNum:    1,
 399				CurrentIdx:             0,
 400			},
 401			Vars:      *setup.RollupVariables,
 402			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 403			Events:    eth.NewRollupEvents(),
 404			Constants: setup.RollupConstants,
 405		},
 406		Auction: &AuctionBlock{
 407			State: eth.AuctionState{
 408				Slots:           make(map[int64]*eth.SlotState),
 409				PendingBalances: make(map[ethCommon.Address]*big.Int),
 410				Coordinators:    make(map[ethCommon.Address]*eth.Coordinator),
 411			},
 412			Vars:      *setup.AuctionVariables,
 413			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 414			Events:    eth.NewAuctionEvents(),
 415			Constants: setup.AuctionConstants,
 416		},
 417		WDelayer: &WDelayerBlock{
 418			// State: TODO
 419			Vars:      *setup.WDelayerVariables,
 420			Txs:       make(map[ethCommon.Hash]*types.Transaction),
 421			Events:    eth.NewWDelayerEvents(),
 422			Constants: setup.WDelayerConstants,
 423		},
 424		Eth: &EthereumBlock{
 425			BlockNum:   blockNum,
 426			Time:       timer.Time(),
 427			Hash:       hasher.Next(),
 428			ParentHash: ethCommon.Hash{},
 429			Tokens:     make(map[ethCommon.Address]eth.ERC20Consts),
 430		},
 431	}
 432	blockCurrent.Rollup.Eth = blockCurrent.Eth
 433	blockCurrent.Auction.Eth = blockCurrent.Eth
 434	blocks[blockNum] = blockCurrent
 435	blockNext := blockCurrent.Next()
 436	blocks[blockNum+1] = blockNext
 437
 438	c := Client{
 439		rw:                    &sync.RWMutex{},
 440		log:                   l,
 441		addr:                  addr,
 442		rollupConstants:       setup.RollupConstants,
 443		auctionConstants:      setup.AuctionConstants,
 444		wDelayerConstants:     setup.WDelayerConstants,
 445		blocks:                blocks,
 446		timer:                 timer,
 447		hasher:                hasher,
 448		forgeBatchArgsPending: make(map[ethCommon.Hash]*batch),
 449		forgeBatchArgs:        make(map[ethCommon.Hash]*batch),
 450		blockNum:              blockNum,
 451		maxBlockNum:           blockNum,
 452	}
 453
 454	for i := int64(1); i < setup.AuctionConstants.GenesisBlockNum+1; i++ {
 455		c.CtlMineBlock()
 456	}
 457
 458	return &c
 459}
 460
 461//
 462// Mock Control
 463//
 464
 465func (c *Client) setNextBlock(block *Block) {
 466	c.blocks[c.blockNum+1] = block
 467}
 468
 469func (c *Client) revertIfErr(err error, block *Block) {
 470	if err != nil {
 471		log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
 472		c.setNextBlock(block)
 473	}
 474}
 475
 476// Debugf calls log.Debugf if c.log is true
 477func (c *Client) Debugf(template string, args ...interface{}) {
 478	if c.log {
 479		log.Debugf(template, args...)
 480	}
 481}
 482
 483// Debugw calls log.Debugw if c.log is true
 484func (c *Client) Debugw(template string, kv ...interface{}) {
 485	if c.log {
 486		log.Debugw(template, kv...)
 487	}
 488}
 489
 490type hasher struct {
 491	counter uint64
 492}
 493
 494// Next returns the next hash
 495func (h *hasher) Next() ethCommon.Hash {
 496	var hash ethCommon.Hash
 497	binary.LittleEndian.PutUint64(hash[:], h.counter)
 498	h.counter++
 499	return hash
 500}
 501
 502func (c *Client) nextBlock() *Block {
 503	return c.blocks[c.blockNum+1]
 504}
 505
 506func (c *Client) currentBlock() *Block {
 507	return c.blocks[c.blockNum]
 508}
 509
 510// CtlSetAddr sets the address of the client
 511func (c *Client) CtlSetAddr(addr ethCommon.Address) {
 512	c.addr = &addr
 513}
 514
 515// CtlMineBlock moves one block forward
 516func (c *Client) CtlMineBlock() {
 517	c.rw.Lock()
 518	defer c.rw.Unlock()
 519
 520	blockCurrent := c.nextBlock()
 521	c.blockNum++
 522	c.maxBlockNum = c.blockNum
 523	blockCurrent.Eth.Time = c.timer.Time()
 524	blockCurrent.Eth.Hash = c.hasher.Next()
 525	for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
 526		c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
 527	}
 528	c.forgeBatchArgsPending = make(map[ethCommon.Hash]*batch)
 529
 530	blockNext := blockCurrent.Next()
 531	c.blocks[c.blockNum+1] = blockNext
 532	c.Debugw("TestClient mined block", "blockNum", c.blockNum)
 533}
 534
 535// CtlRollback discards the last mined block.  Use this to replace a mined
 536// block to simulate reorgs.
 537func (c *Client) CtlRollback() {
 538	c.rw.Lock()
 539	defer c.rw.Unlock()
 540
 541	if c.blockNum == 0 {
 542		panic("Can't rollback at blockNum = 0")
 543	}
 544	delete(c.blocks, c.blockNum+1) // delete next block
 545	delete(c.blocks, c.blockNum)   // delete current block
 546	c.blockNum--
 547	blockCurrent := c.blocks[c.blockNum]
 548	blockNext := blockCurrent.Next()
 549	c.blocks[c.blockNum+1] = blockNext
 550}
 551
 552//
 553// Ethereum
 554//
 555
 556// CtlLastBlock returns the last blockNum without checks
 557func (c *Client) CtlLastBlock() *common.Block {
 558	c.rw.RLock()
 559	defer c.rw.RUnlock()
 560
 561	block := c.blocks[c.blockNum]
 562	return &common.Block{
 563		Num:        c.blockNum,
 564		Timestamp:  time.Unix(block.Eth.Time, 0),
 565		Hash:       block.Eth.Hash,
 566		ParentHash: block.Eth.ParentHash,
 567	}
 568}
 569
 570// EthLastBlock returns the last blockNum
 571func (c *Client) EthLastBlock() (int64, error) {
 572	c.rw.RLock()
 573	defer c.rw.RUnlock()
 574
 575	if c.blockNum < c.maxBlockNum {
 576		panic("blockNum has decreased.  " +
 577			"After a rollback you must mine to reach the same or higher blockNum")
 578	}
 579	return c.blockNum, nil
 580}
 581
 582// EthTransactionReceipt returns the transaction receipt of the given txHash
 583func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
 584	c.rw.RLock()
 585	defer c.rw.RUnlock()
 586
 587	for i := int64(0); i < c.blockNum; i++ {
 588		b := c.blocks[i]
 589		_, ok := b.Rollup.Txs[txHash]
 590		if !ok {
 591			_, ok = b.Auction.Txs[txHash]
 592		}
 593		if ok {
 594			return &types.Receipt{
 595				TxHash:      txHash,
 596				Status:      types.ReceiptStatusSuccessful,
 597				BlockHash:   b.Eth.Hash,
 598				BlockNumber: big.NewInt(b.Eth.BlockNum),
 599			}, nil
 600		}
 601	}
 602
 603	return nil, nil
 604}
 605
 606// CtlAddERC20 adds an ERC20 token to the blockchain.
 607func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
 608	nextBlock := c.nextBlock()
 609	e := nextBlock.Eth
 610	e.Tokens[tokenAddr] = constants
 611}
 612
 613// EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
 614func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
 615	currentBlock := c.currentBlock()
 616	e := currentBlock.Eth
 617	if constants, ok := e.Tokens[tokenAddr]; ok {
 618		return &constants, nil
 619	}
 620	return nil, tracerr.Wrap(fmt.Errorf("tokenAddr not found"))
 621}
 622
 623// func newHeader(number *big.Int) *types.Header {
 624// 	return &types.Header{
 625// 		Number: number,
 626// 		Time:   uint64(number.Int64()),
 627// 	}
 628// }
 629
 630// EthHeaderByNumber returns the *types.Header for the given block number in a
 631// deterministic way.
 632// func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
 633// 	return newHeader(number), nil
 634// }
 635
 636// EthBlockByNumber returns the *common.Block for the given block number in a
 637// deterministic way.  If number == -1, the latests known block is returned.
 638func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
 639	c.rw.RLock()
 640	defer c.rw.RUnlock()
 641
 642	if blockNum > c.blockNum {
 643		return nil, ethereum.NotFound
 644	}
 645	if blockNum == -1 {
 646		blockNum = c.blockNum
 647	}
 648	block := c.blocks[blockNum]
 649	return &common.Block{
 650		Num:        blockNum,
 651		Timestamp:  time.Unix(block.Eth.Time, 0),
 652		Hash:       block.Eth.Hash,
 653		ParentHash: block.Eth.ParentHash,
 654	}, nil
 655}
 656
 657// EthAddress returns the ethereum address of the account loaded into the Client
 658func (c *Client) EthAddress() (*ethCommon.Address, error) {
 659	if c.addr == nil {
 660		return nil, tracerr.Wrap(eth.ErrAccountNil)
 661	}
 662	return c.addr, nil
 663}
 664
 665var errTODO = fmt.Errorf("TODO: Not implemented yet")
 666
 667//
 668// Rollup
 669//
 670
 671// CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
 672// func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
 673// 	c.rw.Lock()
 674// 	defer c.rw.Unlock()
 675//
 676// 	nextBlock := c.nextBlock()
 677// 	r := nextBlock.Rollup
 678// 	queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 679// 	if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
 680// 		r.State.LastToForgeL1TxsNum++
 681// 		r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 682// 		queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 683// 	}
 684// 	if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
 685// 		panic("l1Tx.FromIdx > r.State.CurrentIdx")
 686// 	}
 687// 	if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
 688// 		panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
 689// 	}
 690// 	queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
 691// 	r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
 692// 		L1Tx:            *l1Tx,
 693// 		ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
 694// 		Position:        len(queue.L1TxQueue) - 1,
 695// 	})
 696// }
 697
 698// RollupL1UserTxERC20Permit is the interface to call the smart contract function
 699func (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) {
 700	log.Error("TODO")
 701	return nil, tracerr.Wrap(errTODO)
 702}
 703
 704// RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
 705func (c *Client) RollupL1UserTxERC20ETH(
 706	fromBJJ *babyjub.PublicKey,
 707	fromIdx int64,
 708	loadAmount *big.Int,
 709	amount *big.Int,
 710	tokenID uint32,
 711	toIdx int64,
 712) (tx *types.Transaction, err error) {
 713	c.rw.Lock()
 714	defer c.rw.Unlock()
 715	cpy := c.nextBlock().copy()
 716	defer func() { c.revertIfErr(err, cpy) }()
 717
 718	_, err = common.NewFloat16(amount)
 719	if err != nil {
 720		return nil, tracerr.Wrap(err)
 721	}
 722	_, err = common.NewFloat16(loadAmount)
 723	if err != nil {
 724		return nil, tracerr.Wrap(err)
 725	}
 726
 727	nextBlock := c.nextBlock()
 728	r := nextBlock.Rollup
 729	queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 730	if len(queue.L1TxQueue) >= common.RollupConstMaxL1UserTx {
 731		r.State.LastToForgeL1TxsNum++
 732		r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 733		queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
 734	}
 735	if fromIdx > r.State.CurrentIdx {
 736		panic("l1Tx.FromIdx > r.State.CurrentIdx")
 737	}
 738	if int(tokenID)+1 > len(r.State.TokenList) {
 739		panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
 740	}
 741	toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
 742	l1Tx, err := common.NewL1Tx(&common.L1Tx{
 743		FromIdx:         common.Idx(fromIdx),
 744		FromEthAddr:     *c.addr,
 745		FromBJJ:         fromBJJ,
 746		Amount:          amount,
 747		LoadAmount:      loadAmount,
 748		TokenID:         common.TokenID(tokenID),
 749		ToIdx:           common.Idx(toIdx),
 750		ToForgeL1TxsNum: &toForgeL1TxsNum,
 751		Position:        len(queue.L1TxQueue),
 752		UserOrigin:      true,
 753	})
 754	if err != nil {
 755		return nil, tracerr.Wrap(err)
 756	}
 757
 758	queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
 759	r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
 760		L1UserTx: *l1Tx,
 761	})
 762	return r.addTransaction(newTransaction("l1UserTxERC20ETH", l1Tx)), nil
 763}
 764
 765// RollupL1UserTxERC777 is the interface to call the smart contract function
 766// func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
 767// 	log.Error("TODO")
 768// 	return nil, errTODO
 769// }
 770
 771// RollupRegisterTokensCount is the interface to call the smart contract function
 772func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
 773	log.Error("TODO")
 774	return nil, tracerr.Wrap(errTODO)
 775}
 776
 777// RollupLastForgedBatch is the interface to call the smart contract function
 778func (c *Client) RollupLastForgedBatch() (int64, error) {
 779	c.rw.RLock()
 780	defer c.rw.RUnlock()
 781
 782	currentBlock := c.currentBlock()
 783	e := currentBlock.Rollup
 784	return int64(len(e.State.ExitRoots)) - 1, nil
 785}
 786
 787// RollupWithdrawCircuit is the interface to call the smart contract function
 788func (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) {
 789	log.Error("TODO")
 790	return nil, tracerr.Wrap(errTODO)
 791}
 792
 793// RollupWithdrawMerkleProof is the interface to call the smart contract function
 794func (c *Client) RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (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
 800	nextBlock := c.nextBlock()
 801	r := nextBlock.Rollup
 802
 803	if int(numExitRoot) >= len(r.State.ExitRoots) {
 804		return nil, tracerr.Wrap(fmt.Errorf("numExitRoot >= len(r.State.ExitRoots)"))
 805	}
 806	if _, ok := r.State.ExitNullifierMap[numExitRoot][idx]; ok {
 807		return nil, tracerr.Wrap(fmt.Errorf("exit already withdrawn"))
 808	}
 809	r.State.ExitNullifierMap[numExitRoot][idx] = true
 810
 811	type data struct {
 812		BabyPubKey      *babyjub.PublicKey
 813		TokenID         uint32
 814		NumExitRoot     int64
 815		Idx             int64
 816		Amount          *big.Int
 817		Siblings        []*big.Int
 818		InstantWithdraw bool
 819	}
 820	tx = r.addTransaction(newTransaction("withdrawMerkleProof", data{
 821		BabyPubKey:      babyPubKey,
 822		TokenID:         tokenID,
 823		NumExitRoot:     numExitRoot,
 824		Idx:             idx,
 825		Amount:          amount,
 826		Siblings:        siblings,
 827		InstantWithdraw: instantWithdraw,
 828	}))
 829	r.Events.Withdraw = append(r.Events.Withdraw, eth.RollupEventWithdraw{
 830		Idx:             uint64(idx),
 831		NumExitRoot:     uint64(numExitRoot),
 832		InstantWithdraw: instantWithdraw,
 833		TxHash:          tx.Hash(),
 834	})
 835
 836	if !instantWithdraw {
 837		w := nextBlock.WDelayer
 838		w.deposit(tx.Hash(), *c.addr, r.State.TokenList[int(tokenID)], amount)
 839	}
 840	return tx, nil
 841}
 842
 843type transactionData struct {
 844	Name  string
 845	Value interface{}
 846}
 847
 848func newTransaction(name string, value interface{}) *types.Transaction {
 849	data, err := json.Marshal(transactionData{name, value})
 850	if err != nil {
 851		panic(err)
 852	}
 853	return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
 854		data)
 855}
 856
 857// RollupForgeBatch is the interface to call the smart contract function
 858func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
 859	c.rw.Lock()
 860	defer c.rw.Unlock()
 861	cpy := c.nextBlock().copy()
 862	defer func() { c.revertIfErr(err, cpy) }()
 863	if c.addr == nil {
 864		return nil, tracerr.Wrap(eth.ErrAccountNil)
 865	}
 866
 867	a := c.nextBlock().Auction
 868	ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
 869	if err != nil {
 870		return nil, tracerr.Wrap(err)
 871	}
 872	if !ok {
 873		return nil, tracerr.Wrap(fmt.Errorf("incorrect slot"))
 874	}
 875
 876	// TODO: Verify proof
 877
 878	// Auction
 879	err = a.forge(*c.addr)
 880	if err != nil {
 881		return nil, tracerr.Wrap(err)
 882	}
 883
 884	// TODO: If successful, store the tx in a successful array.
 885	// TODO: If failed, store the tx in a failed array.
 886	// TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
 887
 888	return c.addBatch(args)
 889}
 890
 891// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
 892func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
 893	c.rw.Lock()
 894	defer c.rw.Unlock()
 895
 896	if _, err := c.addBatch(args); err != nil {
 897		panic(err)
 898	}
 899}
 900
 901func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
 902	nextBlock := c.nextBlock()
 903	r := nextBlock.Rollup
 904	r.State.StateRoot = args.NewStRoot
 905	if args.NewLastIdx < r.State.CurrentIdx {
 906		return nil, tracerr.Wrap(fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx"))
 907	}
 908	r.State.CurrentIdx = args.NewLastIdx
 909	r.State.ExitNullifierMap[int64(len(r.State.ExitRoots))] = make(map[int64]bool)
 910	r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
 911	if args.L1Batch {
 912		r.State.CurrentToForgeL1TxsNum++
 913		if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
 914			r.State.LastToForgeL1TxsNum++
 915			r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
 916		}
 917	}
 918	ethTx := r.addTransaction(newTransaction("forgebatch", args))
 919	c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
 920	r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
 921		BatchNum:  int64(len(r.State.ExitRoots)) - 1,
 922		EthTxHash: ethTx.Hash(),
 923	})
 924
 925	return ethTx, nil
 926}
 927
 928// RollupAddTokenSimple is a wrapper around RollupAddToken that automatically
 929// sets `deadlie`.
 930func (c *Client) RollupAddTokenSimple(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
 931	return c.RollupAddToken(tokenAddress, feeAddToken, big.NewInt(9999)) //nolint:gomnd
 932}
 933
 934// RollupAddToken is the interface to call the smart contract function
 935func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int,
 936	deadline *big.Int) (tx *types.Transaction, err error) {
 937	c.rw.Lock()
 938	defer c.rw.Unlock()
 939	cpy := c.nextBlock().copy()
 940	defer func() { c.revertIfErr(err, cpy) }()
 941	if c.addr == nil {
 942		return nil, tracerr.Wrap(eth.ErrAccountNil)
 943	}
 944
 945	nextBlock := c.nextBlock()
 946	r := nextBlock.Rollup
 947	if _, ok := r.State.TokenMap[tokenAddress]; ok {
 948		return nil, tracerr.Wrap(fmt.Errorf("Token %v already registered", tokenAddress))
 949	}
 950	if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
 951		return nil, tracerr.Wrap(fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken))
 952	}
 953
 954	r.State.TokenMap[tokenAddress] = true
 955	r.State.TokenList = append(r.State.TokenList, tokenAddress)
 956	r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
 957		TokenID: uint32(len(r.State.TokenList) - 1)})
 958	return r.addTransaction(newTransaction("addtoken", tokenAddress)), nil
 959}
 960
 961// RollupGetCurrentTokens is the interface to call the smart contract function
 962func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
 963	c.rw.RLock()
 964	defer c.rw.RUnlock()
 965
 966	log.Error("TODO")
 967	return nil, tracerr.Wrap(errTODO)
 968}
 969
 970// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
 971func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
 972	c.rw.Lock()
 973	defer c.rw.Unlock()
 974	cpy := c.nextBlock().copy()
 975	defer func() { c.revertIfErr(err, cpy) }()
 976	if c.addr == nil {
 977		return nil, tracerr.Wrap(eth.ErrAccountNil)
 978	}
 979
 980	nextBlock := c.nextBlock()
 981	r := nextBlock.Rollup
 982	r.Vars.ForgeL1L2BatchTimeout = newForgeL1Timeout
 983	r.Events.UpdateForgeL1L2BatchTimeout = append(r.Events.UpdateForgeL1L2BatchTimeout,
 984		eth.RollupEventUpdateForgeL1L2BatchTimeout{NewForgeL1L2BatchTimeout: newForgeL1Timeout})
 985
 986	return r.addTransaction(newTransaction("updateForgeL1L2BatchTimeout", newForgeL1Timeout)), nil
 987}
 988
 989// RollupUpdateFeeAddToken is the interface to call the smart contract function
 990func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
 991	c.rw.Lock()
 992	defer c.rw.Unlock()
 993	cpy := c.nextBlock().copy()
 994	defer func() { c.revertIfErr(err, cpy) }()
 995	if c.addr == nil {
 996		return nil, tracerr.Wrap(eth.ErrAccountNil)
 997	}
 998
 999	log.Error("TODO")
1000	return nil, tracerr.Wrap(errTODO)
1001}
1002
1003// RollupUpdateTokensHEZ is the interface to call the smart contract function
1004// func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
1005// 	c.rw.Lock()
1006// 	defer c.rw.Unlock()
1007// 	cpy := c.nextBlock().copy()
1008// 	defer func() { c.revertIfErr(err, cpy) }()
1009//
1010// 	log.Error("TODO")
1011// 	return nil, errTODO
1012// }
1013
1014// RollupUpdateGovernance is the interface to call the smart contract function
1015// func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
1016// 	return nil, errTODO
1017// }
1018
1019// RollupConstants returns the Constants of the Rollup Smart Contract
1020func (c *Client) RollupConstants() (*common.RollupConstants, error) {
1021	c.rw.RLock()
1022	defer c.rw.RUnlock()
1023
1024	return c.rollupConstants, nil
1025}
1026
1027// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
1028func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
1029	c.rw.RLock()
1030	defer c.rw.RUnlock()
1031
1032	block, ok := c.blocks[blockNum]
1033	if !ok {
1034		return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1035	}
1036	return &block.Rollup.Events, &block.Eth.Hash, nil
1037}
1038
1039// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
1040func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
1041	c.rw.RLock()
1042	defer c.rw.RUnlock()
1043
1044	batch, ok := c.forgeBatchArgs[ethTxHash]
1045	if !ok {
1046		return nil, nil, tracerr.Wrap(fmt.Errorf("transaction not found"))
1047	}
1048	return &batch.ForgeBatchArgs, &batch.Sender, nil
1049}
1050
1051//
1052// Auction
1053//
1054
1055// AuctionSetSlotDeadline is the interface to call the smart contract function
1056func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
1057	c.rw.Lock()
1058	defer c.rw.Unlock()
1059	cpy := c.nextBlock().copy()
1060	defer func() { c.revertIfErr(err, cpy) }()
1061	if c.addr == nil {
1062		return nil, tracerr.Wrap(eth.ErrAccountNil)
1063	}
1064
1065	log.Error("TODO")
1066	return nil, tracerr.Wrap(errTODO)
1067}
1068
1069// AuctionGetSlotDeadline is the interface to call the smart contract function
1070func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
1071	c.rw.RLock()
1072	defer c.rw.RUnlock()
1073
1074	log.Error("TODO")
1075	return 0, tracerr.Wrap(errTODO)
1076}
1077
1078// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
1079func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
1080	c.rw.Lock()
1081	defer c.rw.Unlock()
1082	cpy := c.nextBlock().copy()
1083	defer func() { c.revertIfErr(err, cpy) }()
1084	if c.addr == nil {
1085		return nil, tracerr.Wrap(eth.ErrAccountNil)
1086	}
1087
1088	nextBlock := c.nextBlock()
1089	a := nextBlock.Auction
1090	a.Vars.OpenAuctionSlots = newOpenAuctionSlots
1091	a.Events.NewOpenAuctionSlots = append(a.Events.NewOpenAuctionSlots,
1092		eth.AuctionEventNewOpenAuctionSlots{NewOpenAuctionSlots: newOpenAuctionSlots})
1093
1094	return a.addTransaction(newTransaction("setOpenAuctionSlots", newOpenAuctionSlots)), nil
1095}
1096
1097// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
1098func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
1099	c.rw.RLock()
1100	defer c.rw.RUnlock()
1101
1102	log.Error("TODO")
1103	return 0, tracerr.Wrap(errTODO)
1104}
1105
1106// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
1107func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
1108	c.rw.Lock()
1109	defer c.rw.Unlock()
1110	cpy := c.nextBlock().copy()
1111	defer func() { c.revertIfErr(err, cpy) }()
1112	if c.addr == nil {
1113		return nil, tracerr.Wrap(eth.ErrAccountNil)
1114	}
1115
1116	log.Error("TODO")
1117	return nil, tracerr.Wrap(errTODO)
1118}
1119
1120// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
1121func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
1122	c.rw.RLock()
1123	defer c.rw.RUnlock()
1124
1125	log.Error("TODO")
1126	return 0, tracerr.Wrap(errTODO)
1127}
1128
1129// AuctionSetOutbidding is the interface to call the smart contract function
1130func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
1131	c.rw.Lock()
1132	defer c.rw.Unlock()
1133	cpy := c.nextBlock().copy()
1134	defer func() { c.revertIfErr(err, cpy) }()
1135	if c.addr == nil {
1136		return nil, tracerr.Wrap(eth.ErrAccountNil)
1137	}
1138
1139	log.Error("TODO")
1140	return nil, tracerr.Wrap(errTODO)
1141}
1142
1143// AuctionGetOutbidding is the interface to call the smart contract function
1144func (c *Client) AuctionGetOutbidding() (uint16, error) {
1145	c.rw.RLock()
1146	defer c.rw.RUnlock()
1147
1148	log.Error("TODO")
1149	return 0, tracerr.Wrap(errTODO)
1150}
1151
1152// AuctionSetAllocationRatio is the interface to call the smart contract function
1153func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
1154	c.rw.Lock()
1155	defer c.rw.Unlock()
1156	cpy := c.nextBlock().copy()
1157	defer func() { c.revertIfErr(err, cpy) }()
1158	if c.addr == nil {
1159		return nil, tracerr.Wrap(eth.ErrAccountNil)
1160	}
1161
1162	log.Error("TODO")
1163	return nil, tracerr.Wrap(errTODO)
1164}
1165
1166// AuctionGetAllocationRatio is the interface to call the smart contract function
1167func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
1168	c.rw.RLock()
1169	defer c.rw.RUnlock()
1170
1171	log.Error("TODO")
1172	return [3]uint16{}, tracerr.Wrap(errTODO)
1173}
1174
1175// AuctionSetDonationAddress is the interface to call the smart contract function
1176func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
1177	c.rw.Lock()
1178	defer c.rw.Unlock()
1179	cpy := c.nextBlock().copy()
1180	defer func() { c.revertIfErr(err, cpy) }()
1181	if c.addr == nil {
1182		return nil, tracerr.Wrap(eth.ErrAccountNil)
1183	}
1184
1185	log.Error("TODO")
1186	return nil, tracerr.Wrap(errTODO)
1187}
1188
1189// AuctionGetDonationAddress is the interface to call the smart contract function
1190func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
1191	c.rw.RLock()
1192	defer c.rw.RUnlock()
1193
1194	log.Error("TODO")
1195	return nil, tracerr.Wrap(errTODO)
1196}
1197
1198// AuctionSetBootCoordinator is the interface to call the smart contract function
1199func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
1200	c.rw.Lock()
1201	defer c.rw.Unlock()
1202	cpy := c.nextBlock().copy()
1203	defer func() { c.revertIfErr(err, cpy) }()
1204	if c.addr == nil {
1205		return nil, tracerr.Wrap(eth.ErrAccountNil)
1206	}
1207
1208	log.Error("TODO")
1209	return nil, tracerr.Wrap(errTODO)
1210}
1211
1212// AuctionGetBootCoordinator is the interface to call the smart contract function
1213func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
1214	c.rw.RLock()
1215	defer c.rw.RUnlock()
1216
1217	currentBlock := c.currentBlock()
1218	a := currentBlock.Auction
1219
1220	return &a.Vars.BootCoordinator, nil
1221}
1222
1223// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
1224func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
1225	c.rw.Lock()
1226	defer c.rw.Unlock()
1227	cpy := c.nextBlock().copy()
1228	defer func() { c.revertIfErr(err, cpy) }()
1229	if c.addr == nil {
1230		return nil, tracerr.Wrap(eth.ErrAccountNil)
1231	}
1232
1233	log.Error("TODO")
1234	return nil, tracerr.Wrap(errTODO)
1235}
1236
1237// AuctionSetCoordinator is the interface to call the smart contract function
1238func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
1239	c.rw.Lock()
1240	defer c.rw.Unlock()
1241	cpy := c.nextBlock().copy()
1242	defer func() { c.revertIfErr(err, cpy) }()
1243	if c.addr == nil {
1244		return nil, tracerr.Wrap(eth.ErrAccountNil)
1245	}
1246
1247	nextBlock := c.nextBlock()
1248	a := nextBlock.Auction
1249
1250	a.State.Coordinators[*c.addr] = &eth.Coordinator{
1251		Forger: forger,
1252		URL:    URL,
1253	}
1254
1255	a.Events.SetCoordinator = append(a.Events.SetCoordinator,
1256		eth.AuctionEventSetCoordinator{
1257			BidderAddress:  *c.addr,
1258			ForgerAddress:  forger,
1259			CoordinatorURL: URL,
1260		})
1261
1262	type data struct {
1263		BidderAddress ethCommon.Address
1264		ForgerAddress ethCommon.Address
1265		URL           string
1266	}
1267	return a.addTransaction(newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
1268}
1269
1270// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
1271func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
1272	c.rw.RLock()
1273	defer c.rw.RUnlock()
1274
1275	log.Error("TODO")
1276	return false, tracerr.Wrap(errTODO)
1277}
1278
1279// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
1280func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
1281	c.rw.Lock()
1282	defer c.rw.Unlock()
1283	cpy := c.nextBlock().copy()
1284	defer func() { c.revertIfErr(err, cpy) }()
1285	if c.addr == nil {
1286		return nil, tracerr.Wrap(eth.ErrAccountNil)
1287	}
1288
1289	log.Error("TODO")
1290	return nil, tracerr.Wrap(errTODO)
1291}
1292
1293// AuctionGetSlotNumber is the interface to call the smart contract function
1294func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
1295	c.rw.RLock()
1296	defer c.rw.RUnlock()
1297
1298	currentBlock := c.currentBlock()
1299	a := currentBlock.Auction
1300	return a.getSlotNumber(blockNum), nil
1301}
1302
1303// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
1304func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
1305	c.rw.RLock()
1306	defer c.rw.RUnlock()
1307
1308	log.Error("TODO")
1309	return 0, tracerr.Wrap(errTODO)
1310}
1311
1312// AuctionGetMinBidBySlot is the interface to call the smart contract function
1313func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
1314	c.rw.RLock()
1315	defer c.rw.RUnlock()
1316
1317	log.Error("TODO")
1318	return nil, tracerr.Wrap(errTODO)
1319}
1320
1321// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
1322func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
1323	c.rw.RLock()
1324	defer c.rw.RUnlock()
1325
1326	log.Error("TODO")
1327	return nil, tracerr.Wrap(errTODO)
1328}
1329
1330// AuctionGetSlotSet is the interface to call the smart contract function
1331func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
1332	c.rw.RLock()
1333	defer c.rw.RUnlock()
1334
1335	log.Error("TODO")
1336	return nil, tracerr.Wrap(errTODO)
1337}
1338
1339// AuctionTokensReceived is the interface to call the smart contract function
1340// func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
1341// 	return errTODO
1342// }
1343
1344// AuctionBidSimple is a wrapper around AuctionBid that automatically sets `amount` and `deadline`.
1345func (c *Client) AuctionBidSimple(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
1346	return c.AuctionBid(bidAmount, slot, bidAmount, big.NewInt(99999)) //nolint:gomnd
1347}
1348
1349// AuctionBid is the interface to call the smart contract function.  This
1350// implementation behaves as if any address has infinite tokens.
1351func (c *Client) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
1352	deadline *big.Int) (tx *types.Transaction, err error) {
1353	c.rw.Lock()
1354	defer c.rw.Unlock()
1355	cpy := c.nextBlock().copy()
1356	defer func() { func() { c.revertIfErr(err, cpy) }() }()
1357	if c.addr == nil {
1358		return nil, tracerr.Wrap(eth.ErrAccountNil)
1359	}
1360
1361	nextBlock := c.nextBlock()
1362	a := nextBlock.Auction
1363
1364	if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
1365		return nil, tracerr.Wrap(errBidClosed)
1366	}
1367
1368	if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
1369		return nil, tracerr.Wrap(errBidNotOpen)
1370	}
1371
1372	minBid, err := a.getMinBidBySlot(slot)
1373	if err != nil {
1374		return nil, tracerr.Wrap(err)
1375	}
1376	if bidAmount.Cmp(minBid) == -1 {
1377		return nil, tracerr.Wrap(errBidBelowMin)
1378	}
1379
1380	if _, ok := a.State.Coordinators[*c.addr]; !ok {
1381		return nil, tracerr.Wrap(errCoordNotReg)
1382	}
1383
1384	slotState, ok := a.State.Slots[slot]
1385	if !ok {
1386		slotState = eth.NewSlotState()
1387		a.State.Slots[slot] = slotState
1388	}
1389	slotState.Bidder = *c.addr
1390	slotState.BidAmount = bidAmount
1391
1392	a.Events.NewBid = append(a.Events.NewBid,
1393		eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
1394
1395	type data struct {
1396		Slot      int64
1397		BidAmount *big.Int
1398		Bidder    ethCommon.Address
1399	}
1400	return a.addTransaction(newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
1401}
1402
1403// AuctionMultiBid is the interface to call the smart contract function.  This
1404// implementation behaves as if any address has infinite tokens.
1405func (c *Client) AuctionMultiBid(amount *big.Int, startingSlot int64, endingSlot int64, slotSet [6]bool,
1406	maxBid, closedMinBid, deadline *big.Int) (tx *types.Transaction, err error) {
1407	c.rw.Lock()
1408	defer c.rw.Unlock()
1409	cpy := c.nextBlock().copy()
1410	defer func() { c.revertIfErr(err, cpy) }()
1411	if c.addr == nil {
1412		return nil, tracerr.Wrap(eth.ErrAccountNil)
1413	}
1414
1415	log.Error("TODO")
1416	return nil, tracerr.Wrap(errTODO)
1417}
1418
1419// AuctionCanForge is the interface to call the smart contract function
1420func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
1421	c.rw.RLock()
1422	defer c.rw.RUnlock()
1423
1424	currentBlock := c.currentBlock()
1425	a := currentBlock.Auction
1426	return a.canForge(forger, blockNum)
1427}
1428
1429// AuctionForge is the interface to call the smart contract function
1430func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
1431	c.rw.Lock()
1432	defer c.rw.Unlock()
1433	cpy := c.nextBlock().copy()
1434	defer func() { c.revertIfErr(err, cpy) }()
1435	if c.addr == nil {
1436		return nil, tracerr.Wrap(eth.ErrAccountNil)
1437	}
1438
1439	log.Error("TODO")
1440	return nil, tracerr.Wrap(errTODO)
1441}
1442
1443// AuctionClaimHEZ is the interface to call the smart contract function
1444func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
1445	c.rw.Lock()
1446	defer c.rw.Unlock()
1447	cpy := c.nextBlock().copy()
1448	defer func() { c.revertIfErr(err, cpy) }()
1449	if c.addr == nil {
1450		return nil, tracerr.Wrap(eth.ErrAccountNil)
1451	}
1452
1453	log.Error("TODO")
1454	return nil, tracerr.Wrap(errTODO)
1455}
1456
1457// AuctionGetClaimableHEZ is the interface to call the smart contract function
1458func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
1459	c.rw.RLock()
1460	defer c.rw.RUnlock()
1461
1462	log.Error("TODO")
1463	return nil, tracerr.Wrap(errTODO)
1464}
1465
1466// AuctionConstants returns the Constants of the Auction Smart Contract
1467func (c *Client) AuctionConstants() (*common.AuctionConstants, error) {
1468	c.rw.RLock()
1469	defer c.rw.RUnlock()
1470
1471	return c.auctionConstants, nil
1472}
1473
1474// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
1475func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
1476	c.rw.RLock()
1477	defer c.rw.RUnlock()
1478
1479	block, ok := c.blocks[blockNum]
1480	if !ok {
1481		return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1482	}
1483	return &block.Auction.Events, &block.Eth.Hash, nil
1484}
1485
1486//
1487// WDelayer
1488//
1489
1490// WDelayerGetHermezGovernanceDAOAddress is the interface to call the smart contract function
1491func (c *Client) WDelayerGetHermezGovernanceDAOAddress() (*ethCommon.Address, error) {
1492	c.rw.RLock()
1493	defer c.rw.RUnlock()
1494
1495	log.Error("TODO")
1496	return nil, tracerr.Wrap(errTODO)
1497}
1498
1499// WDelayerSetHermezGovernanceDAOAddress is the interface to call the smart contract function
1500func (c *Client) WDelayerSetHermezGovernanceDAOAddress(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1501	c.rw.Lock()
1502	defer c.rw.Unlock()
1503	cpy := c.nextBlock().copy()
1504	defer func() { c.revertIfErr(err, cpy) }()
1505	if c.addr == nil {
1506		return nil, tracerr.Wrap(eth.ErrAccountNil)
1507	}
1508
1509	log.Error("TODO")
1510	return nil, tracerr.Wrap(errTODO)
1511}
1512
1513// WDelayerGetHermezKeeperAddress is the interface to call the smart contract function
1514func (c *Client) WDelayerGetHermezKeeperAddress() (*ethCommon.Address, error) {
1515	c.rw.RLock()
1516	defer c.rw.RUnlock()
1517
1518	log.Error("TODO")
1519	return nil, tracerr.Wrap(errTODO)
1520}
1521
1522// WDelayerSetHermezKeeperAddress is the interface to call the smart contract function
1523func (c *Client) WDelayerSetHermezKeeperAddress(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1524	c.rw.Lock()
1525	defer c.rw.Unlock()
1526	cpy := c.nextBlock().copy()
1527	defer func() { c.revertIfErr(err, cpy) }()
1528	if c.addr == nil {
1529		return nil, tracerr.Wrap(eth.ErrAccountNil)
1530	}
1531
1532	log.Error("TODO")
1533	return nil, tracerr.Wrap(errTODO)
1534}
1535
1536// WDelayerGetWhiteHackGroupAddress is the interface to call the smart contract function
1537func (c *Client) WDelayerGetWhiteHackGroupAddress() (*ethCommon.Address, error) {
1538	c.rw.RLock()
1539	defer c.rw.RUnlock()
1540
1541	log.Error("TODO")
1542	return nil, tracerr.Wrap(errTODO)
1543}
1544
1545// WDelayerSetWhiteHackGroupAddress is the interface to call the smart contract function
1546func (c *Client) WDelayerSetWhiteHackGroupAddress(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1547	c.rw.Lock()
1548	defer c.rw.Unlock()
1549	cpy := c.nextBlock().copy()
1550	defer func() { c.revertIfErr(err, cpy) }()
1551	if c.addr == nil {
1552		return nil, tracerr.Wrap(eth.ErrAccountNil)
1553	}
1554
1555	log.Error("TODO")
1556	return nil, tracerr.Wrap(errTODO)
1557}
1558
1559// WDelayerIsEmergencyMode is the interface to call the smart contract function
1560func (c *Client) WDelayerIsEmergencyMode() (bool, error) {
1561	c.rw.RLock()
1562	defer c.rw.RUnlock()
1563
1564	log.Error("TODO")
1565	return false, tracerr.Wrap(errTODO)
1566}
1567
1568// WDelayerGetWithdrawalDelay is the interface to call the smart contract function
1569func (c *Client) WDelayerGetWithdrawalDelay() (*big.Int, error) {
1570	c.rw.RLock()
1571	defer c.rw.RUnlock()
1572
1573	log.Error("TODO")
1574	return nil, tracerr.Wrap(errTODO)
1575}
1576
1577// WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
1578func (c *Client) WDelayerGetEmergencyModeStartingTime() (*big.Int, error) {
1579	c.rw.RLock()
1580	defer c.rw.RUnlock()
1581
1582	log.Error("TODO")
1583	return nil, tracerr.Wrap(errTODO)
1584}
1585
1586// WDelayerEnableEmergencyMode is the interface to call the smart contract function
1587func (c *Client) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
1588	c.rw.Lock()
1589	defer c.rw.Unlock()
1590	cpy := c.nextBlock().copy()
1591	defer func() { c.revertIfErr(err, cpy) }()
1592	if c.addr == nil {
1593		return nil, tracerr.Wrap(eth.ErrAccountNil)
1594	}
1595
1596	log.Error("TODO")
1597	return nil, tracerr.Wrap(errTODO)
1598}
1599
1600// WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
1601func (c *Client) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction, err error) {
1602	c.rw.Lock()
1603	defer c.rw.Unlock()
1604	cpy := c.nextBlock().copy()
1605	defer func() { c.revertIfErr(err, cpy) }()
1606	if c.addr == nil {
1607		return nil, tracerr.Wrap(eth.ErrAccountNil)
1608	}
1609
1610	nextBlock := c.nextBlock()
1611	w := nextBlock.WDelayer
1612	w.Vars.WithdrawalDelay = newWithdrawalDelay
1613	w.Events.NewWithdrawalDelay = append(w.Events.NewWithdrawalDelay,
1614		eth.WDelayerEventNewWithdrawalDelay{WithdrawalDelay: newWithdrawalDelay})
1615
1616	return w.addTransaction(newTransaction("changeWithdrawalDelay", newWithdrawalDelay)), nil
1617}
1618
1619// WDelayerDepositInfo is the interface to call the smart contract function
1620func (c *Client) WDelayerDepositInfo(owner, token ethCommon.Address) (eth.DepositState, error) {
1621	c.rw.RLock()
1622	defer c.rw.RUnlock()
1623
1624	log.Error("TODO")
1625	return eth.DepositState{}, tracerr.Wrap(errTODO)
1626}
1627
1628// WDelayerDeposit is the interface to call the smart contract function
1629func (c *Client) WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
1630	c.rw.Lock()
1631	defer c.rw.Unlock()
1632	cpy := c.nextBlock().copy()
1633	defer func() { c.revertIfErr(err, cpy) }()
1634	if c.addr == nil {
1635		return nil, tracerr.Wrap(eth.ErrAccountNil)
1636	}
1637
1638	log.Error("TODO")
1639	return nil, tracerr.Wrap(errTODO)
1640}
1641
1642// WDelayerWithdrawal is the interface to call the smart contract function
1643func (c *Client) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction, err error) {
1644	c.rw.Lock()
1645	defer c.rw.Unlock()
1646	cpy := c.nextBlock().copy()
1647	defer func() { c.revertIfErr(err, cpy) }()
1648	if c.addr == nil {
1649		return nil, tracerr.Wrap(eth.ErrAccountNil)
1650	}
1651
1652	log.Error("TODO")
1653	return nil, tracerr.Wrap(errTODO)
1654}
1655
1656// WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
1657func (c *Client) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
1658	c.rw.Lock()
1659	defer c.rw.Unlock()
1660	cpy := c.nextBlock().copy()
1661	defer func() { c.revertIfErr(err, cpy) }()
1662	if c.addr == nil {
1663		return nil, tracerr.Wrap(eth.ErrAccountNil)
1664	}
1665
1666	log.Error("TODO")
1667	return nil, tracerr.Wrap(errTODO)
1668}
1669
1670// WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Contract
1671func (c *Client) WDelayerEventsByBlock(blockNum int64) (*eth.WDelayerEvents, *ethCommon.Hash, error) {
1672	c.rw.RLock()
1673	defer c.rw.RUnlock()
1674
1675	block, ok := c.blocks[blockNum]
1676	if !ok {
1677		return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1678	}
1679	return &block.WDelayer.Events, &block.Eth.Hash, nil
1680}
1681
1682// WDelayerConstants returns the Constants of the WDelayer Contract
1683func (c *Client) WDelayerConstants() (*common.WDelayerConstants, error) {
1684	c.rw.RLock()
1685	defer c.rw.RUnlock()
1686
1687	return c.wDelayerConstants, nil
1688}