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