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