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