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
404// NewClient returns a new test Client that implements the eth.IClient
405// interface, at the given initialBlockNumber.
406func NewClient(l bool, timer Timer, addr *ethCommon.Address, setup *ClientSetup) *Client {
407 blocks := make(map[int64]*Block)
408 blockNum := int64(0)
409
410 hasher := hasher{}
411 // Add ethereum genesis block
412 mapL1TxQueue := make(map[int64]*eth.QueueStruct)
413 mapL1TxQueue[0] = eth.NewQueueStruct()
414 mapL1TxQueue[1] = eth.NewQueueStruct()
415 blockCurrent := &Block{
416 Rollup: &RollupBlock{
417 State: eth.RollupState{
418 StateRoot: big.NewInt(0),
419 ExitRoots: make([]*big.Int, 1),
420 ExitNullifierMap: make(map[int64]map[int64]bool),
421 // TokenID = 0 is ETH. Set first entry in TokenList with 0x0 address for ETH.
422 TokenList: []ethCommon.Address{{}},
423 TokenMap: make(map[ethCommon.Address]bool),
424 MapL1TxQueue: mapL1TxQueue,
425 LastL1L2Batch: 0,
426 CurrentToForgeL1TxsNum: 0,
427 LastToForgeL1TxsNum: 1,
428 CurrentIdx: 0,
429 },
430 Vars: *setup.RollupVariables,
431 Txs: make(map[ethCommon.Hash]*types.Transaction),
432 Events: eth.NewRollupEvents(),
433 Constants: setup.RollupConstants,
434 },
435 Auction: &AuctionBlock{
436 State: eth.AuctionState{
437 Slots: make(map[int64]*eth.SlotState),
438 PendingBalances: make(map[ethCommon.Address]*big.Int),
439 Coordinators: make(map[ethCommon.Address]*eth.Coordinator),
440 },
441 Vars: *setup.AuctionVariables,
442 Txs: make(map[ethCommon.Hash]*types.Transaction),
443 Events: eth.NewAuctionEvents(),
444 Constants: setup.AuctionConstants,
445 },
446 WDelayer: &WDelayerBlock{
447 // State: TODO
448 Vars: *setup.WDelayerVariables,
449 Txs: make(map[ethCommon.Hash]*types.Transaction),
450 Events: eth.NewWDelayerEvents(),
451 Constants: setup.WDelayerConstants,
452 },
453 Eth: &EthereumBlock{
454 BlockNum: blockNum,
455 Time: timer.Time(),
456 Hash: hasher.Next(),
457 ParentHash: ethCommon.Hash{},
458 Tokens: make(map[ethCommon.Address]eth.ERC20Consts),
459 },
460 }
461 blockCurrent.Rollup.Eth = blockCurrent.Eth
462 blockCurrent.Auction.Eth = blockCurrent.Eth
463 blocks[blockNum] = blockCurrent
464 blockNext := blockCurrent.Next()
465 blocks[blockNum+1] = blockNext
466
467 c := Client{
468 rw: &sync.RWMutex{},
469 log: l,
470 addr: addr,
471 rollupConstants: setup.RollupConstants,
472 auctionConstants: setup.AuctionConstants,
473 wDelayerConstants: setup.WDelayerConstants,
474 blocks: blocks,
475 timer: timer,
476 hasher: hasher,
477 forgeBatchArgsPending: make(map[ethCommon.Hash]*batch),
478 forgeBatchArgs: make(map[ethCommon.Hash]*batch),
479 blockNum: blockNum,
480 maxBlockNum: blockNum,
481 }
482
483 for i := int64(1); i < setup.AuctionConstants.GenesisBlockNum+1; i++ {
484 c.CtlMineBlock()
485 }
486
487 return &c
488}
489
490//
491// Mock Control
492//
493
494func (c *Client) setNextBlock(block *Block) {
495 c.blocks[c.blockNum+1] = block
496}
497
498func (c *Client) revertIfErr(err error, block *Block) {
499 if err != nil {
500 log.Infow("TestClient revert", "block", block.Eth.BlockNum, "err", err)
501 c.setNextBlock(block)
502 }
503}
504
505// Debugf calls log.Debugf if c.log is true
506func (c *Client) Debugf(template string, args ...interface{}) {
507 if c.log {
508 log.Debugf(template, args...)
509 }
510}
511
512// Debugw calls log.Debugw if c.log is true
513func (c *Client) Debugw(template string, kv ...interface{}) {
514 if c.log {
515 log.Debugw(template, kv...)
516 }
517}
518
519type hasher struct {
520 counter uint64
521}
522
523// Next returns the next hash
524func (h *hasher) Next() ethCommon.Hash {
525 var hash ethCommon.Hash
526 binary.LittleEndian.PutUint64(hash[:], h.counter)
527 h.counter++
528 return hash
529}
530
531func (c *Client) nextBlock() *Block {
532 return c.blocks[c.blockNum+1]
533}
534
535func (c *Client) currentBlock() *Block {
536 return c.blocks[c.blockNum]
537}
538
539// CtlSetAddr sets the address of the client
540func (c *Client) CtlSetAddr(addr ethCommon.Address) {
541 c.addr = &addr
542}
543
544// CtlMineBlock moves one block forward
545func (c *Client) CtlMineBlock() {
546 c.rw.Lock()
547 defer c.rw.Unlock()
548
549 blockCurrent := c.nextBlock()
550 c.blockNum++
551 c.maxBlockNum = c.blockNum
552 blockCurrent.Eth.Time = c.timer.Time()
553 blockCurrent.Eth.Hash = c.hasher.Next()
554 for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
555 c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
556 }
557 c.forgeBatchArgsPending = make(map[ethCommon.Hash]*batch)
558
559 blockNext := blockCurrent.Next()
560 c.blocks[c.blockNum+1] = blockNext
561 c.Debugw("TestClient mined block", "blockNum", c.blockNum)
562}
563
564// CtlRollback discards the last mined block. Use this to replace a mined
565// block to simulate reorgs.
566func (c *Client) CtlRollback() {
567 c.rw.Lock()
568 defer c.rw.Unlock()
569
570 if c.blockNum == 0 {
571 panic("Can't rollback at blockNum = 0")
572 }
573 delete(c.blocks, c.blockNum+1) // delete next block
574 delete(c.blocks, c.blockNum) // delete current block
575 c.blockNum--
576 blockCurrent := c.blocks[c.blockNum]
577 blockNext := blockCurrent.Next()
578 c.blocks[c.blockNum+1] = blockNext
579}
580
581//
582// Ethereum
583//
584
585// CtlLastBlock returns the last blockNum without checks
586func (c *Client) CtlLastBlock() *common.Block {
587 c.rw.RLock()
588 defer c.rw.RUnlock()
589
590 block := c.blocks[c.blockNum]
591 return &common.Block{
592 Num: c.blockNum,
593 Timestamp: time.Unix(block.Eth.Time, 0),
594 Hash: block.Eth.Hash,
595 ParentHash: block.Eth.ParentHash,
596 }
597}
598
599// CtlLastForgedBatch returns the last batchNum without checks
600func (c *Client) CtlLastForgedBatch() int64 {
601 c.rw.RLock()
602 defer c.rw.RUnlock()
603
604 currentBlock := c.currentBlock()
605 e := currentBlock.Rollup
606 return int64(len(e.State.ExitRoots)) - 1
607}
608
609// EthChainID returns the ChainID of the ethereum network
610func (c *Client) EthChainID() (*big.Int, error) {
611 return c.chainID, nil
612}
613
614// EthLastBlock returns the last blockNum
615func (c *Client) EthLastBlock() (int64, error) {
616 c.rw.RLock()
617 defer c.rw.RUnlock()
618
619 if c.blockNum < c.maxBlockNum {
620 panic("blockNum has decreased. " +
621 "After a rollback you must mine to reach the same or higher blockNum")
622 }
623 return c.blockNum, nil
624}
625
626// EthTransactionReceipt returns the transaction receipt of the given txHash
627func (c *Client) EthTransactionReceipt(ctx context.Context, txHash ethCommon.Hash) (*types.Receipt, error) {
628 c.rw.RLock()
629 defer c.rw.RUnlock()
630
631 for i := int64(0); i < c.blockNum; i++ {
632 b := c.blocks[i]
633 _, ok := b.Rollup.Txs[txHash]
634 if !ok {
635 _, ok = b.Auction.Txs[txHash]
636 }
637 if ok {
638 return &types.Receipt{
639 TxHash: txHash,
640 Status: types.ReceiptStatusSuccessful,
641 BlockHash: b.Eth.Hash,
642 BlockNumber: big.NewInt(b.Eth.BlockNum),
643 }, nil
644 }
645 }
646
647 return nil, nil
648}
649
650// CtlAddERC20 adds an ERC20 token to the blockchain.
651func (c *Client) CtlAddERC20(tokenAddr ethCommon.Address, constants eth.ERC20Consts) {
652 nextBlock := c.nextBlock()
653 e := nextBlock.Eth
654 e.Tokens[tokenAddr] = constants
655}
656
657// EthERC20Consts returns the constants defined for a particular ERC20 Token instance.
658func (c *Client) EthERC20Consts(tokenAddr ethCommon.Address) (*eth.ERC20Consts, error) {
659 currentBlock := c.currentBlock()
660 e := currentBlock.Eth
661 if constants, ok := e.Tokens[tokenAddr]; ok {
662 return &constants, nil
663 }
664 return nil, tracerr.Wrap(fmt.Errorf("tokenAddr not found"))
665}
666
667// func newHeader(number *big.Int) *types.Header {
668// return &types.Header{
669// Number: number,
670// Time: uint64(number.Int64()),
671// }
672// }
673
674// EthHeaderByNumber returns the *types.Header for the given block number in a
675// deterministic way.
676// func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
677// return newHeader(number), nil
678// }
679
680// EthBlockByNumber returns the *common.Block for the given block number in a
681// deterministic way. If number == -1, the latests known block is returned.
682func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
683 c.rw.RLock()
684 defer c.rw.RUnlock()
685
686 if blockNum > c.blockNum {
687 return nil, ethereum.NotFound
688 }
689 if blockNum == -1 {
690 blockNum = c.blockNum
691 }
692 block := c.blocks[blockNum]
693 return &common.Block{
694 Num: blockNum,
695 Timestamp: time.Unix(block.Eth.Time, 0),
696 Hash: block.Eth.Hash,
697 ParentHash: block.Eth.ParentHash,
698 }, nil
699}
700
701// EthAddress returns the ethereum address of the account loaded into the Client
702func (c *Client) EthAddress() (*ethCommon.Address, error) {
703 if c.addr == nil {
704 return nil, tracerr.Wrap(eth.ErrAccountNil)
705 }
706 return c.addr, nil
707}
708
709var errTODO = fmt.Errorf("TODO: Not implemented yet")
710
711//
712// Rollup
713//
714
715// CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
716// func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
717// c.rw.Lock()
718// defer c.rw.Unlock()
719//
720// nextBlock := c.nextBlock()
721// r := nextBlock.Rollup
722// queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
723// if len(queue.L1TxQueue) >= eth.RollupConstMaxL1UserTx {
724// r.State.LastToForgeL1TxsNum++
725// r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
726// queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
727// }
728// if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
729// panic("l1Tx.FromIdx > r.State.CurrentIdx")
730// }
731// if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
732// panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
733// }
734// queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
735// r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
736// L1Tx: *l1Tx,
737// ToForgeL1TxsNum: r.State.LastToForgeL1TxsNum,
738// Position: len(queue.L1TxQueue) - 1,
739// })
740// }
741
742// RollupL1UserTxERC20Permit is the interface to call the smart contract function
743func (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) {
744 log.Error("TODO")
745 return nil, tracerr.Wrap(errTODO)
746}
747
748// RollupL1UserTxERC20ETH sends an L1UserTx to the Rollup.
749func (c *Client) RollupL1UserTxERC20ETH(
750 fromBJJ babyjub.PublicKeyComp,
751 fromIdx int64,
752 depositAmount *big.Int,
753 amount *big.Int,
754 tokenID uint32,
755 toIdx int64,
756) (tx *types.Transaction, err error) {
757 c.rw.Lock()
758 defer c.rw.Unlock()
759 cpy := c.nextBlock().copy()
760 defer func() { c.revertIfErr(err, cpy) }()
761
762 _, err = common.NewFloat16(amount)
763 if err != nil {
764 return nil, tracerr.Wrap(err)
765 }
766 _, err = common.NewFloat16(depositAmount)
767 if err != nil {
768 return nil, tracerr.Wrap(err)
769 }
770
771 nextBlock := c.nextBlock()
772 r := nextBlock.Rollup
773 queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
774 if len(queue.L1TxQueue) >= common.RollupConstMaxL1UserTx {
775 r.State.LastToForgeL1TxsNum++
776 r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
777 queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
778 }
779 if fromIdx > r.State.CurrentIdx {
780 panic("l1Tx.FromIdx > r.State.CurrentIdx")
781 }
782 if int(tokenID)+1 > len(r.State.TokenList) {
783 panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
784 }
785 toForgeL1TxsNum := r.State.LastToForgeL1TxsNum
786 l1Tx, err := common.NewL1Tx(&common.L1Tx{
787 FromIdx: common.Idx(fromIdx),
788 FromEthAddr: *c.addr,
789 FromBJJ: fromBJJ,
790 Amount: amount,
791 DepositAmount: depositAmount,
792 TokenID: common.TokenID(tokenID),
793 ToIdx: common.Idx(toIdx),
794 ToForgeL1TxsNum: &toForgeL1TxsNum,
795 Position: len(queue.L1TxQueue),
796 UserOrigin: true,
797 })
798 if err != nil {
799 return nil, tracerr.Wrap(err)
800 }
801
802 queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
803 r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{
804 L1UserTx: *l1Tx,
805 })
806 return r.addTransaction(c.newTransaction("l1UserTxERC20ETH", l1Tx)), nil
807}
808
809// RollupL1UserTxERC777 is the interface to call the smart contract function
810// func (c *Client) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, depositAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error) {
811// log.Error("TODO")
812// return nil, errTODO
813// }
814
815// RollupRegisterTokensCount is the interface to call the smart contract function
816func (c *Client) RollupRegisterTokensCount() (*big.Int, error) {
817 log.Error("TODO")
818 return nil, tracerr.Wrap(errTODO)
819}
820
821// RollupLastForgedBatch is the interface to call the smart contract function
822func (c *Client) RollupLastForgedBatch() (int64, error) {
823 c.rw.RLock()
824 defer c.rw.RUnlock()
825
826 currentBlock := c.currentBlock()
827 e := currentBlock.Rollup
828 return int64(len(e.State.ExitRoots)) - 1, nil
829}
830
831// RollupWithdrawCircuit is the interface to call the smart contract function
832func (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) {
833 log.Error("TODO")
834 return nil, tracerr.Wrap(errTODO)
835}
836
837// RollupWithdrawMerkleProof is the interface to call the smart contract function
838func (c *Client) RollupWithdrawMerkleProof(babyPubKey babyjub.PublicKeyComp, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (tx *types.Transaction, err error) {
839 c.rw.Lock()
840 defer c.rw.Unlock()
841 cpy := c.nextBlock().copy()
842 defer func() { c.revertIfErr(err, cpy) }()
843
844 nextBlock := c.nextBlock()
845 r := nextBlock.Rollup
846
847 if int(numExitRoot) >= len(r.State.ExitRoots) {
848 return nil, tracerr.Wrap(fmt.Errorf("numExitRoot >= len(r.State.ExitRoots)"))
849 }
850 if _, ok := r.State.ExitNullifierMap[numExitRoot][idx]; ok {
851 return nil, tracerr.Wrap(fmt.Errorf("exit already withdrawn"))
852 }
853 r.State.ExitNullifierMap[numExitRoot][idx] = true
854
855 babyPubKeyDecomp, err := babyPubKey.Decompress()
856 if err != nil {
857 return nil, tracerr.Wrap(err)
858 }
859
860 type data struct {
861 BabyPubKey *babyjub.PublicKey
862 TokenID uint32
863 NumExitRoot int64
864 Idx int64
865 Amount *big.Int
866 Siblings []*big.Int
867 InstantWithdraw bool
868 }
869 tx = r.addTransaction(c.newTransaction("withdrawMerkleProof", data{
870 BabyPubKey: babyPubKeyDecomp,
871 TokenID: tokenID,
872 NumExitRoot: numExitRoot,
873 Idx: idx,
874 Amount: amount,
875 Siblings: siblings,
876 InstantWithdraw: instantWithdraw,
877 }))
878 r.Events.Withdraw = append(r.Events.Withdraw, eth.RollupEventWithdraw{
879 Idx: uint64(idx),
880 NumExitRoot: uint64(numExitRoot),
881 InstantWithdraw: instantWithdraw,
882 TxHash: tx.Hash(),
883 })
884
885 if !instantWithdraw {
886 w := nextBlock.WDelayer
887 w.deposit(tx.Hash(), *c.addr, r.State.TokenList[int(tokenID)], amount)
888 }
889 return tx, nil
890}
891
892type transactionData struct {
893 Name string
894 Value interface{}
895}
896
897func (c *Client) newTransaction(name string, value interface{}) *types.Transaction {
898 eth := c.nextBlock().Eth
899 nonce := eth.Nonce
900 eth.Nonce++
901 data, err := json.Marshal(transactionData{name, value})
902 if err != nil {
903 panic(err)
904 }
905 return types.NewTransaction(nonce, ethCommon.Address{}, nil, 0, nil,
906 data)
907}
908
909// RollupForgeBatch is the interface to call the smart contract function
910func (c *Client) RollupForgeBatch(args *eth.RollupForgeBatchArgs) (tx *types.Transaction, err error) {
911 c.rw.Lock()
912 defer c.rw.Unlock()
913 cpy := c.nextBlock().copy()
914 defer func() { c.revertIfErr(err, cpy) }()
915 if c.addr == nil {
916 return nil, tracerr.Wrap(eth.ErrAccountNil)
917 }
918
919 a := c.nextBlock().Auction
920 ok, err := a.canForge(*c.addr, a.Eth.BlockNum)
921 if err != nil {
922 return nil, tracerr.Wrap(err)
923 }
924 if !ok {
925 return nil, tracerr.Wrap(fmt.Errorf(common.AuctionErrMsgCannotForge))
926 }
927
928 // TODO: Verify proof
929
930 // Auction
931 err = a.forge(*c.addr)
932 if err != nil {
933 return nil, tracerr.Wrap(err)
934 }
935
936 // TODO: If successful, store the tx in a successful array.
937 // TODO: If failed, store the tx in a failed array.
938 // TODO: Add method to move the tx to another block, reapply it there, and possibly go from successful to failed.
939
940 return c.addBatch(args)
941}
942
943// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
944func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
945 c.rw.Lock()
946 defer c.rw.Unlock()
947
948 if _, err := c.addBatch(args); err != nil {
949 panic(err)
950 }
951}
952
953func (c *Client) addBatch(args *eth.RollupForgeBatchArgs) (*types.Transaction, error) {
954 nextBlock := c.nextBlock()
955 r := nextBlock.Rollup
956 r.State.StateRoot = args.NewStRoot
957 if args.NewLastIdx < r.State.CurrentIdx {
958 return nil, tracerr.Wrap(fmt.Errorf("args.NewLastIdx < r.State.CurrentIdx"))
959 }
960 r.State.CurrentIdx = args.NewLastIdx
961 r.State.ExitNullifierMap[int64(len(r.State.ExitRoots))] = make(map[int64]bool)
962 r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
963 if args.L1Batch {
964 r.State.CurrentToForgeL1TxsNum++
965 if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
966 r.State.LastToForgeL1TxsNum++
967 r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
968 }
969 }
970 ethTx := r.addTransaction(c.newTransaction("forgebatch", args))
971 c.forgeBatchArgsPending[ethTx.Hash()] = &batch{*args, *c.addr}
972 r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
973 BatchNum: int64(len(r.State.ExitRoots)) - 1,
974 EthTxHash: ethTx.Hash(),
975 L1UserTxsLen: uint16(len(args.L1UserTxs)),
976 })
977
978 return ethTx, nil
979}
980
981// RollupAddTokenSimple is a wrapper around RollupAddToken that automatically
982// sets `deadlie`.
983func (c *Client) RollupAddTokenSimple(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
984 return c.RollupAddToken(tokenAddress, feeAddToken, big.NewInt(9999)) //nolint:gomnd
985}
986
987// RollupAddToken is the interface to call the smart contract function
988func (c *Client) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int,
989 deadline *big.Int) (tx *types.Transaction, err error) {
990 c.rw.Lock()
991 defer c.rw.Unlock()
992 cpy := c.nextBlock().copy()
993 defer func() { c.revertIfErr(err, cpy) }()
994 if c.addr == nil {
995 return nil, tracerr.Wrap(eth.ErrAccountNil)
996 }
997
998 nextBlock := c.nextBlock()
999 r := nextBlock.Rollup
1000 if _, ok := r.State.TokenMap[tokenAddress]; ok {
1001 return nil, tracerr.Wrap(fmt.Errorf("Token %v already registered", tokenAddress))
1002 }
1003 if feeAddToken.Cmp(r.Vars.FeeAddToken) != 0 {
1004 return nil, tracerr.Wrap(fmt.Errorf("Expected fee: %v but got: %v", r.Vars.FeeAddToken, feeAddToken))
1005 }
1006
1007 r.State.TokenMap[tokenAddress] = true
1008 r.State.TokenList = append(r.State.TokenList, tokenAddress)
1009 r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{TokenAddress: tokenAddress,
1010 TokenID: uint32(len(r.State.TokenList) - 1)})
1011 return r.addTransaction(c.newTransaction("addtoken", tokenAddress)), nil
1012}
1013
1014// RollupGetCurrentTokens is the interface to call the smart contract function
1015func (c *Client) RollupGetCurrentTokens() (*big.Int, error) {
1016 c.rw.RLock()
1017 defer c.rw.RUnlock()
1018
1019 log.Error("TODO")
1020 return nil, tracerr.Wrap(errTODO)
1021}
1022
1023// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
1024func (c *Client) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (tx *types.Transaction, err error) {
1025 c.rw.Lock()
1026 defer c.rw.Unlock()
1027 cpy := c.nextBlock().copy()
1028 defer func() { c.revertIfErr(err, cpy) }()
1029 if c.addr == nil {
1030 return nil, tracerr.Wrap(eth.ErrAccountNil)
1031 }
1032
1033 nextBlock := c.nextBlock()
1034 r := nextBlock.Rollup
1035 r.Vars.ForgeL1L2BatchTimeout = newForgeL1Timeout
1036 r.Events.UpdateForgeL1L2BatchTimeout = append(r.Events.UpdateForgeL1L2BatchTimeout,
1037 eth.RollupEventUpdateForgeL1L2BatchTimeout{NewForgeL1L2BatchTimeout: newForgeL1Timeout})
1038
1039 return r.addTransaction(c.newTransaction("updateForgeL1L2BatchTimeout", newForgeL1Timeout)), nil
1040}
1041
1042// RollupUpdateFeeAddToken is the interface to call the smart contract function
1043func (c *Client) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
1044 c.rw.Lock()
1045 defer c.rw.Unlock()
1046 cpy := c.nextBlock().copy()
1047 defer func() { c.revertIfErr(err, cpy) }()
1048 if c.addr == nil {
1049 return nil, tracerr.Wrap(eth.ErrAccountNil)
1050 }
1051
1052 log.Error("TODO")
1053 return nil, tracerr.Wrap(errTODO)
1054}
1055
1056// RollupUpdateTokensHEZ is the interface to call the smart contract function
1057// func (c *Client) RollupUpdateTokensHEZ(newTokenHEZ ethCommon.Address) (tx *types.Transaction, err error) {
1058// c.rw.Lock()
1059// defer c.rw.Unlock()
1060// cpy := c.nextBlock().copy()
1061// defer func() { c.revertIfErr(err, cpy) }()
1062//
1063// log.Error("TODO")
1064// return nil, errTODO
1065// }
1066
1067// RollupUpdateGovernance is the interface to call the smart contract function
1068// func (c *Client) RollupUpdateGovernance() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
1069// return nil, errTODO
1070// }
1071
1072// RollupConstants returns the Constants of the Rollup Smart Contract
1073func (c *Client) RollupConstants() (*common.RollupConstants, error) {
1074 c.rw.RLock()
1075 defer c.rw.RUnlock()
1076
1077 return c.rollupConstants, nil
1078}
1079
1080// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
1081func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
1082 c.rw.RLock()
1083 defer c.rw.RUnlock()
1084
1085 block, ok := c.blocks[blockNum]
1086 if !ok {
1087 return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1088 }
1089 return &block.Rollup.Events, &block.Eth.Hash, nil
1090}
1091
1092// RollupEventInit returns the initialize event with its corresponding block number
1093func (c *Client) RollupEventInit() (*eth.RollupEventInitialize, int64, error) {
1094 vars := c.blocks[0].Rollup.Vars
1095 return ð.RollupEventInitialize{
1096 ForgeL1L2BatchTimeout: uint8(vars.ForgeL1L2BatchTimeout),
1097 FeeAddToken: vars.FeeAddToken,
1098 WithdrawalDelay: vars.WithdrawalDelay,
1099 }, 1, nil
1100}
1101
1102// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
1103func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash, l1UserTxsLen uint16) (*eth.RollupForgeBatchArgs, *ethCommon.Address, error) {
1104 c.rw.RLock()
1105 defer c.rw.RUnlock()
1106
1107 batch, ok := c.forgeBatchArgs[ethTxHash]
1108 if !ok {
1109 return nil, nil, tracerr.Wrap(fmt.Errorf("transaction not found"))
1110 }
1111 return &batch.ForgeBatchArgs, &batch.Sender, nil
1112}
1113
1114//
1115// Auction
1116//
1117
1118// AuctionSetSlotDeadline is the interface to call the smart contract function
1119func (c *Client) AuctionSetSlotDeadline(newDeadline uint8) (tx *types.Transaction, err error) {
1120 c.rw.Lock()
1121 defer c.rw.Unlock()
1122 cpy := c.nextBlock().copy()
1123 defer func() { c.revertIfErr(err, cpy) }()
1124 if c.addr == nil {
1125 return nil, tracerr.Wrap(eth.ErrAccountNil)
1126 }
1127
1128 log.Error("TODO")
1129 return nil, tracerr.Wrap(errTODO)
1130}
1131
1132// AuctionGetSlotDeadline is the interface to call the smart contract function
1133func (c *Client) AuctionGetSlotDeadline() (uint8, error) {
1134 c.rw.RLock()
1135 defer c.rw.RUnlock()
1136
1137 log.Error("TODO")
1138 return 0, tracerr.Wrap(errTODO)
1139}
1140
1141// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
1142func (c *Client) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
1143 c.rw.Lock()
1144 defer c.rw.Unlock()
1145 cpy := c.nextBlock().copy()
1146 defer func() { c.revertIfErr(err, cpy) }()
1147 if c.addr == nil {
1148 return nil, tracerr.Wrap(eth.ErrAccountNil)
1149 }
1150
1151 nextBlock := c.nextBlock()
1152 a := nextBlock.Auction
1153 a.Vars.OpenAuctionSlots = newOpenAuctionSlots
1154 a.Events.NewOpenAuctionSlots = append(a.Events.NewOpenAuctionSlots,
1155 eth.AuctionEventNewOpenAuctionSlots{NewOpenAuctionSlots: newOpenAuctionSlots})
1156
1157 return a.addTransaction(c.newTransaction("setOpenAuctionSlots", newOpenAuctionSlots)), nil
1158}
1159
1160// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
1161func (c *Client) AuctionGetOpenAuctionSlots() (uint16, error) {
1162 c.rw.RLock()
1163 defer c.rw.RUnlock()
1164
1165 log.Error("TODO")
1166 return 0, tracerr.Wrap(errTODO)
1167}
1168
1169// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
1170func (c *Client) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
1171 c.rw.Lock()
1172 defer c.rw.Unlock()
1173 cpy := c.nextBlock().copy()
1174 defer func() { c.revertIfErr(err, cpy) }()
1175 if c.addr == nil {
1176 return nil, tracerr.Wrap(eth.ErrAccountNil)
1177 }
1178
1179 log.Error("TODO")
1180 return nil, tracerr.Wrap(errTODO)
1181}
1182
1183// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
1184func (c *Client) AuctionGetClosedAuctionSlots() (uint16, error) {
1185 c.rw.RLock()
1186 defer c.rw.RUnlock()
1187
1188 log.Error("TODO")
1189 return 0, tracerr.Wrap(errTODO)
1190}
1191
1192// AuctionSetOutbidding is the interface to call the smart contract function
1193func (c *Client) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
1194 c.rw.Lock()
1195 defer c.rw.Unlock()
1196 cpy := c.nextBlock().copy()
1197 defer func() { c.revertIfErr(err, cpy) }()
1198 if c.addr == nil {
1199 return nil, tracerr.Wrap(eth.ErrAccountNil)
1200 }
1201
1202 log.Error("TODO")
1203 return nil, tracerr.Wrap(errTODO)
1204}
1205
1206// AuctionGetOutbidding is the interface to call the smart contract function
1207func (c *Client) AuctionGetOutbidding() (uint16, error) {
1208 c.rw.RLock()
1209 defer c.rw.RUnlock()
1210
1211 log.Error("TODO")
1212 return 0, tracerr.Wrap(errTODO)
1213}
1214
1215// AuctionSetAllocationRatio is the interface to call the smart contract function
1216func (c *Client) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
1217 c.rw.Lock()
1218 defer c.rw.Unlock()
1219 cpy := c.nextBlock().copy()
1220 defer func() { c.revertIfErr(err, cpy) }()
1221 if c.addr == nil {
1222 return nil, tracerr.Wrap(eth.ErrAccountNil)
1223 }
1224
1225 log.Error("TODO")
1226 return nil, tracerr.Wrap(errTODO)
1227}
1228
1229// AuctionGetAllocationRatio is the interface to call the smart contract function
1230func (c *Client) AuctionGetAllocationRatio() ([3]uint16, error) {
1231 c.rw.RLock()
1232 defer c.rw.RUnlock()
1233
1234 log.Error("TODO")
1235 return [3]uint16{}, tracerr.Wrap(errTODO)
1236}
1237
1238// AuctionSetDonationAddress is the interface to call the smart contract function
1239func (c *Client) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
1240 c.rw.Lock()
1241 defer c.rw.Unlock()
1242 cpy := c.nextBlock().copy()
1243 defer func() { c.revertIfErr(err, cpy) }()
1244 if c.addr == nil {
1245 return nil, tracerr.Wrap(eth.ErrAccountNil)
1246 }
1247
1248 log.Error("TODO")
1249 return nil, tracerr.Wrap(errTODO)
1250}
1251
1252// AuctionGetDonationAddress is the interface to call the smart contract function
1253func (c *Client) AuctionGetDonationAddress() (*ethCommon.Address, error) {
1254 c.rw.RLock()
1255 defer c.rw.RUnlock()
1256
1257 log.Error("TODO")
1258 return nil, tracerr.Wrap(errTODO)
1259}
1260
1261// AuctionSetBootCoordinator is the interface to call the smart contract function
1262func (c *Client) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (tx *types.Transaction, err error) {
1263 c.rw.Lock()
1264 defer c.rw.Unlock()
1265 cpy := c.nextBlock().copy()
1266 defer func() { c.revertIfErr(err, cpy) }()
1267 if c.addr == nil {
1268 return nil, tracerr.Wrap(eth.ErrAccountNil)
1269 }
1270
1271 log.Error("TODO")
1272 return nil, tracerr.Wrap(errTODO)
1273}
1274
1275// AuctionGetBootCoordinator is the interface to call the smart contract function
1276func (c *Client) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
1277 c.rw.RLock()
1278 defer c.rw.RUnlock()
1279
1280 currentBlock := c.currentBlock()
1281 a := currentBlock.Auction
1282
1283 return &a.Vars.BootCoordinator, nil
1284}
1285
1286// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
1287func (c *Client) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
1288 c.rw.Lock()
1289 defer c.rw.Unlock()
1290 cpy := c.nextBlock().copy()
1291 defer func() { c.revertIfErr(err, cpy) }()
1292 if c.addr == nil {
1293 return nil, tracerr.Wrap(eth.ErrAccountNil)
1294 }
1295
1296 log.Error("TODO")
1297 return nil, tracerr.Wrap(errTODO)
1298}
1299
1300// AuctionSetCoordinator is the interface to call the smart contract function
1301func (c *Client) AuctionSetCoordinator(forger ethCommon.Address, URL string) (tx *types.Transaction, err error) {
1302 c.rw.Lock()
1303 defer c.rw.Unlock()
1304 cpy := c.nextBlock().copy()
1305 defer func() { c.revertIfErr(err, cpy) }()
1306 if c.addr == nil {
1307 return nil, tracerr.Wrap(eth.ErrAccountNil)
1308 }
1309
1310 nextBlock := c.nextBlock()
1311 a := nextBlock.Auction
1312
1313 a.State.Coordinators[*c.addr] = ð.Coordinator{
1314 Forger: forger,
1315 URL: URL,
1316 }
1317
1318 a.Events.SetCoordinator = append(a.Events.SetCoordinator,
1319 eth.AuctionEventSetCoordinator{
1320 BidderAddress: *c.addr,
1321 ForgerAddress: forger,
1322 CoordinatorURL: URL,
1323 })
1324
1325 type data struct {
1326 BidderAddress ethCommon.Address
1327 ForgerAddress ethCommon.Address
1328 URL string
1329 }
1330 return a.addTransaction(c.newTransaction("registercoordinator", data{*c.addr, forger, URL})), nil
1331}
1332
1333// AuctionIsRegisteredCoordinator is the interface to call the smart contract function
1334func (c *Client) AuctionIsRegisteredCoordinator(forgerAddress ethCommon.Address) (bool, error) {
1335 c.rw.RLock()
1336 defer c.rw.RUnlock()
1337
1338 log.Error("TODO")
1339 return false, tracerr.Wrap(errTODO)
1340}
1341
1342// AuctionUpdateCoordinatorInfo is the interface to call the smart contract function
1343func (c *Client) AuctionUpdateCoordinatorInfo(forgerAddress ethCommon.Address, newWithdrawAddress ethCommon.Address, newURL string) (tx *types.Transaction, err error) {
1344 c.rw.Lock()
1345 defer c.rw.Unlock()
1346 cpy := c.nextBlock().copy()
1347 defer func() { c.revertIfErr(err, cpy) }()
1348 if c.addr == nil {
1349 return nil, tracerr.Wrap(eth.ErrAccountNil)
1350 }
1351
1352 log.Error("TODO")
1353 return nil, tracerr.Wrap(errTODO)
1354}
1355
1356// AuctionGetSlotNumber is the interface to call the smart contract function
1357func (c *Client) AuctionGetSlotNumber(blockNum int64) (int64, error) {
1358 c.rw.RLock()
1359 defer c.rw.RUnlock()
1360
1361 currentBlock := c.currentBlock()
1362 a := currentBlock.Auction
1363 return a.getSlotNumber(blockNum), nil
1364}
1365
1366// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
1367func (c *Client) AuctionGetCurrentSlotNumber() (int64, error) {
1368 c.rw.RLock()
1369 defer c.rw.RUnlock()
1370
1371 log.Error("TODO")
1372 return 0, tracerr.Wrap(errTODO)
1373}
1374
1375// AuctionGetMinBidBySlot is the interface to call the smart contract function
1376func (c *Client) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
1377 c.rw.RLock()
1378 defer c.rw.RUnlock()
1379
1380 log.Error("TODO")
1381 return nil, tracerr.Wrap(errTODO)
1382}
1383
1384// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
1385func (c *Client) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
1386 c.rw.RLock()
1387 defer c.rw.RUnlock()
1388
1389 log.Error("TODO")
1390 return nil, tracerr.Wrap(errTODO)
1391}
1392
1393// AuctionGetSlotSet is the interface to call the smart contract function
1394func (c *Client) AuctionGetSlotSet(slot int64) (*big.Int, error) {
1395 c.rw.RLock()
1396 defer c.rw.RUnlock()
1397
1398 log.Error("TODO")
1399 return nil, tracerr.Wrap(errTODO)
1400}
1401
1402// AuctionTokensReceived is the interface to call the smart contract function
1403// func (c *Client) AuctionTokensReceived(operator, from, to ethCommon.Address, amount *big.Int, userData, operatorData []byte) error {
1404// return errTODO
1405// }
1406
1407// AuctionBidSimple is a wrapper around AuctionBid that automatically sets `amount` and `deadline`.
1408func (c *Client) AuctionBidSimple(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
1409 return c.AuctionBid(bidAmount, slot, bidAmount, big.NewInt(99999)) //nolint:gomnd
1410}
1411
1412// AuctionBid is the interface to call the smart contract function. This
1413// implementation behaves as if any address has infinite tokens.
1414func (c *Client) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
1415 deadline *big.Int) (tx *types.Transaction, err error) {
1416 c.rw.Lock()
1417 defer c.rw.Unlock()
1418 cpy := c.nextBlock().copy()
1419 defer func() { func() { c.revertIfErr(err, cpy) }() }()
1420 if c.addr == nil {
1421 return nil, tracerr.Wrap(eth.ErrAccountNil)
1422 }
1423
1424 nextBlock := c.nextBlock()
1425 a := nextBlock.Auction
1426
1427 if slot < a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots) {
1428 return nil, tracerr.Wrap(errBidClosed)
1429 }
1430
1431 if slot >= a.getCurrentSlotNumber()+int64(a.Vars.ClosedAuctionSlots)+int64(a.Vars.OpenAuctionSlots) {
1432 return nil, tracerr.Wrap(errBidNotOpen)
1433 }
1434
1435 minBid, err := a.getMinBidBySlot(slot)
1436 if err != nil {
1437 return nil, tracerr.Wrap(err)
1438 }
1439 if bidAmount.Cmp(minBid) == -1 {
1440 return nil, tracerr.Wrap(errBidBelowMin)
1441 }
1442
1443 if _, ok := a.State.Coordinators[*c.addr]; !ok {
1444 return nil, tracerr.Wrap(errCoordNotReg)
1445 }
1446
1447 slotState, ok := a.State.Slots[slot]
1448 if !ok {
1449 slotState = eth.NewSlotState()
1450 a.State.Slots[slot] = slotState
1451 }
1452 slotState.Bidder = *c.addr
1453 slotState.BidAmount = bidAmount
1454
1455 a.Events.NewBid = append(a.Events.NewBid,
1456 eth.AuctionEventNewBid{Slot: slot, BidAmount: bidAmount, Bidder: *c.addr})
1457
1458 type data struct {
1459 Slot int64
1460 BidAmount *big.Int
1461 Bidder ethCommon.Address
1462 }
1463 return a.addTransaction(c.newTransaction("bid", data{slot, bidAmount, *c.addr})), nil
1464}
1465
1466// AuctionMultiBid is the interface to call the smart contract function. This
1467// implementation behaves as if any address has infinite tokens.
1468func (c *Client) AuctionMultiBid(amount *big.Int, startingSlot int64, endingSlot int64, slotSet [6]bool,
1469 maxBid, closedMinBid, deadline *big.Int) (tx *types.Transaction, err error) {
1470 c.rw.Lock()
1471 defer c.rw.Unlock()
1472 cpy := c.nextBlock().copy()
1473 defer func() { c.revertIfErr(err, cpy) }()
1474 if c.addr == nil {
1475 return nil, tracerr.Wrap(eth.ErrAccountNil)
1476 }
1477
1478 log.Error("TODO")
1479 return nil, tracerr.Wrap(errTODO)
1480}
1481
1482// AuctionCanForge is the interface to call the smart contract function
1483func (c *Client) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
1484 c.rw.RLock()
1485 defer c.rw.RUnlock()
1486
1487 currentBlock := c.currentBlock()
1488 a := currentBlock.Auction
1489 return a.canForge(forger, blockNum)
1490}
1491
1492// AuctionForge is the interface to call the smart contract function
1493func (c *Client) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
1494 c.rw.Lock()
1495 defer c.rw.Unlock()
1496 cpy := c.nextBlock().copy()
1497 defer func() { c.revertIfErr(err, cpy) }()
1498 if c.addr == nil {
1499 return nil, tracerr.Wrap(eth.ErrAccountNil)
1500 }
1501
1502 log.Error("TODO")
1503 return nil, tracerr.Wrap(errTODO)
1504}
1505
1506// AuctionClaimHEZ is the interface to call the smart contract function
1507func (c *Client) AuctionClaimHEZ() (tx *types.Transaction, err error) {
1508 c.rw.Lock()
1509 defer c.rw.Unlock()
1510 cpy := c.nextBlock().copy()
1511 defer func() { c.revertIfErr(err, cpy) }()
1512 if c.addr == nil {
1513 return nil, tracerr.Wrap(eth.ErrAccountNil)
1514 }
1515
1516 log.Error("TODO")
1517 return nil, tracerr.Wrap(errTODO)
1518}
1519
1520// AuctionGetClaimableHEZ is the interface to call the smart contract function
1521func (c *Client) AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error) {
1522 c.rw.RLock()
1523 defer c.rw.RUnlock()
1524
1525 log.Error("TODO")
1526 return nil, tracerr.Wrap(errTODO)
1527}
1528
1529// AuctionConstants returns the Constants of the Auction Smart Contract
1530func (c *Client) AuctionConstants() (*common.AuctionConstants, error) {
1531 c.rw.RLock()
1532 defer c.rw.RUnlock()
1533
1534 return c.auctionConstants, nil
1535}
1536
1537// AuctionEventsByBlock returns the events in a block that happened in the Auction Smart Contract
1538func (c *Client) AuctionEventsByBlock(blockNum int64) (*eth.AuctionEvents, *ethCommon.Hash, error) {
1539 c.rw.RLock()
1540 defer c.rw.RUnlock()
1541
1542 block, ok := c.blocks[blockNum]
1543 if !ok {
1544 return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1545 }
1546 return &block.Auction.Events, &block.Eth.Hash, nil
1547}
1548
1549// AuctionEventInit returns the initialize event with its corresponding block number
1550func (c *Client) AuctionEventInit() (*eth.AuctionEventInitialize, int64, error) {
1551 vars := c.blocks[0].Auction.Vars
1552 return ð.AuctionEventInitialize{
1553 DonationAddress: vars.DonationAddress,
1554 BootCoordinatorAddress: vars.BootCoordinator,
1555 BootCoordinatorURL: vars.BootCoordinatorURL,
1556 Outbidding: vars.Outbidding,
1557 SlotDeadline: vars.SlotDeadline,
1558 ClosedAuctionSlots: vars.ClosedAuctionSlots,
1559 OpenAuctionSlots: vars.OpenAuctionSlots,
1560 AllocationRatio: vars.AllocationRatio,
1561 }, 1, nil
1562}
1563
1564//
1565// WDelayer
1566//
1567
1568// WDelayerGetHermezGovernanceAddress is the interface to call the smart contract function
1569func (c *Client) WDelayerGetHermezGovernanceAddress() (*ethCommon.Address, error) {
1570 c.rw.RLock()
1571 defer c.rw.RUnlock()
1572
1573 log.Error("TODO")
1574 return nil, tracerr.Wrap(errTODO)
1575}
1576
1577// WDelayerTransferGovernance is the interface to call the smart contract function
1578func (c *Client) WDelayerTransferGovernance(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1579 c.rw.Lock()
1580 defer c.rw.Unlock()
1581 cpy := c.nextBlock().copy()
1582 defer func() { c.revertIfErr(err, cpy) }()
1583 if c.addr == nil {
1584 return nil, tracerr.Wrap(eth.ErrAccountNil)
1585 }
1586
1587 log.Error("TODO")
1588 return nil, tracerr.Wrap(errTODO)
1589}
1590
1591// WDelayerClaimGovernance is the interface to call the smart contract function
1592func (c *Client) WDelayerClaimGovernance() (tx *types.Transaction, err error) {
1593 c.rw.Lock()
1594 defer c.rw.Unlock()
1595 cpy := c.nextBlock().copy()
1596 defer func() { c.revertIfErr(err, cpy) }()
1597 if c.addr == nil {
1598 return nil, tracerr.Wrap(eth.ErrAccountNil)
1599 }
1600
1601 log.Error("TODO")
1602 return nil, tracerr.Wrap(errTODO)
1603}
1604
1605// WDelayerGetEmergencyCouncil is the interface to call the smart contract function
1606func (c *Client) WDelayerGetEmergencyCouncil() (*ethCommon.Address, error) {
1607 c.rw.RLock()
1608 defer c.rw.RUnlock()
1609
1610 log.Error("TODO")
1611 return nil, tracerr.Wrap(errTODO)
1612}
1613
1614// WDelayerTransferEmergencyCouncil is the interface to call the smart contract function
1615func (c *Client) WDelayerTransferEmergencyCouncil(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
1616 c.rw.Lock()
1617 defer c.rw.Unlock()
1618 cpy := c.nextBlock().copy()
1619 defer func() { c.revertIfErr(err, cpy) }()
1620 if c.addr == nil {
1621 return nil, tracerr.Wrap(eth.ErrAccountNil)
1622 }
1623
1624 log.Error("TODO")
1625 return nil, tracerr.Wrap(errTODO)
1626}
1627
1628// WDelayerClaimEmergencyCouncil is the interface to call the smart contract function
1629func (c *Client) WDelayerClaimEmergencyCouncil() (tx *types.Transaction, err error) {
1630 c.rw.Lock()
1631 defer c.rw.Unlock()
1632 cpy := c.nextBlock().copy()
1633 defer func() { c.revertIfErr(err, cpy) }()
1634 if c.addr == nil {
1635 return nil, tracerr.Wrap(eth.ErrAccountNil)
1636 }
1637
1638 log.Error("TODO")
1639 return nil, tracerr.Wrap(errTODO)
1640}
1641
1642// WDelayerIsEmergencyMode is the interface to call the smart contract function
1643func (c *Client) WDelayerIsEmergencyMode() (bool, error) {
1644 c.rw.RLock()
1645 defer c.rw.RUnlock()
1646
1647 log.Error("TODO")
1648 return false, tracerr.Wrap(errTODO)
1649}
1650
1651// WDelayerGetWithdrawalDelay is the interface to call the smart contract function
1652func (c *Client) WDelayerGetWithdrawalDelay() (int64, error) {
1653 c.rw.RLock()
1654 defer c.rw.RUnlock()
1655
1656 log.Error("TODO")
1657 return 0, tracerr.Wrap(errTODO)
1658}
1659
1660// WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
1661func (c *Client) WDelayerGetEmergencyModeStartingTime() (int64, error) {
1662 c.rw.RLock()
1663 defer c.rw.RUnlock()
1664
1665 log.Error("TODO")
1666 return 0, tracerr.Wrap(errTODO)
1667}
1668
1669// WDelayerEnableEmergencyMode is the interface to call the smart contract function
1670func (c *Client) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
1671 c.rw.Lock()
1672 defer c.rw.Unlock()
1673 cpy := c.nextBlock().copy()
1674 defer func() { c.revertIfErr(err, cpy) }()
1675 if c.addr == nil {
1676 return nil, tracerr.Wrap(eth.ErrAccountNil)
1677 }
1678
1679 log.Error("TODO")
1680 return nil, tracerr.Wrap(errTODO)
1681}
1682
1683// WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
1684func (c *Client) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction, err error) {
1685 c.rw.Lock()
1686 defer c.rw.Unlock()
1687 cpy := c.nextBlock().copy()
1688 defer func() { c.revertIfErr(err, cpy) }()
1689 if c.addr == nil {
1690 return nil, tracerr.Wrap(eth.ErrAccountNil)
1691 }
1692
1693 nextBlock := c.nextBlock()
1694 w := nextBlock.WDelayer
1695 w.Vars.WithdrawalDelay = newWithdrawalDelay
1696 w.Events.NewWithdrawalDelay = append(w.Events.NewWithdrawalDelay,
1697 eth.WDelayerEventNewWithdrawalDelay{WithdrawalDelay: newWithdrawalDelay})
1698
1699 return w.addTransaction(c.newTransaction("changeWithdrawalDelay", newWithdrawalDelay)), nil
1700}
1701
1702// WDelayerDepositInfo is the interface to call the smart contract function
1703func (c *Client) WDelayerDepositInfo(owner, token ethCommon.Address) (eth.DepositState, error) {
1704 c.rw.RLock()
1705 defer c.rw.RUnlock()
1706
1707 log.Error("TODO")
1708 return eth.DepositState{}, tracerr.Wrap(errTODO)
1709}
1710
1711// WDelayerDeposit is the interface to call the smart contract function
1712func (c *Client) WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
1713 c.rw.Lock()
1714 defer c.rw.Unlock()
1715 cpy := c.nextBlock().copy()
1716 defer func() { c.revertIfErr(err, cpy) }()
1717 if c.addr == nil {
1718 return nil, tracerr.Wrap(eth.ErrAccountNil)
1719 }
1720
1721 log.Error("TODO")
1722 return nil, tracerr.Wrap(errTODO)
1723}
1724
1725// WDelayerWithdrawal is the interface to call the smart contract function
1726func (c *Client) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction, err error) {
1727 c.rw.Lock()
1728 defer c.rw.Unlock()
1729 cpy := c.nextBlock().copy()
1730 defer func() { c.revertIfErr(err, cpy) }()
1731 if c.addr == nil {
1732 return nil, tracerr.Wrap(eth.ErrAccountNil)
1733 }
1734
1735 log.Error("TODO")
1736 return nil, tracerr.Wrap(errTODO)
1737}
1738
1739// WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
1740func (c *Client) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
1741 c.rw.Lock()
1742 defer c.rw.Unlock()
1743 cpy := c.nextBlock().copy()
1744 defer func() { c.revertIfErr(err, cpy) }()
1745 if c.addr == nil {
1746 return nil, tracerr.Wrap(eth.ErrAccountNil)
1747 }
1748
1749 log.Error("TODO")
1750 return nil, tracerr.Wrap(errTODO)
1751}
1752
1753// WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Contract
1754func (c *Client) WDelayerEventsByBlock(blockNum int64) (*eth.WDelayerEvents, *ethCommon.Hash, error) {
1755 c.rw.RLock()
1756 defer c.rw.RUnlock()
1757
1758 block, ok := c.blocks[blockNum]
1759 if !ok {
1760 return nil, nil, tracerr.Wrap(fmt.Errorf("Block %v doesn't exist", blockNum))
1761 }
1762 return &block.WDelayer.Events, &block.Eth.Hash, nil
1763}
1764
1765// WDelayerConstants returns the Constants of the WDelayer Contract
1766func (c *Client) WDelayerConstants() (*common.WDelayerConstants, error) {
1767 c.rw.RLock()
1768 defer c.rw.RUnlock()
1769
1770 return c.wDelayerConstants, nil
1771}
1772
1773// WDelayerEventInit returns the initialize event with its corresponding block number
1774func (c *Client) WDelayerEventInit() (*eth.WDelayerEventInitialize, int64, error) {
1775 vars := c.blocks[0].WDelayer.Vars
1776 return ð.WDelayerEventInitialize{
1777 InitialWithdrawalDelay: vars.WithdrawalDelay,
1778 InitialHermezGovernanceAddress: vars.HermezGovernanceAddress,
1779 InitialEmergencyCouncil: vars.EmergencyCouncilAddress,
1780 }, 1, nil
1781}
1782
1783// CtlAddBlocks adds block data to the smarts contracts. The added blocks will
1784// appear as mined. Not thread safe.
1785func (c *Client) CtlAddBlocks(blocks []common.BlockData) (err error) {
1786 // NOTE: We don't lock because internally we call public functions that
1787 // lock already.
1788 for _, block := range blocks {
1789 nextBlock := c.nextBlock()
1790 rollup := nextBlock.Rollup
1791 auction := nextBlock.Auction
1792 for _, token := range block.Rollup.AddedTokens {
1793 if _, err := c.RollupAddTokenSimple(token.EthAddr, rollup.Vars.FeeAddToken); err != nil {
1794 return tracerr.Wrap(err)
1795 }
1796 }
1797 for _, tx := range block.Rollup.L1UserTxs {
1798 c.CtlSetAddr(tx.FromEthAddr)
1799 if _, err := c.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.DepositAmount, tx.Amount,
1800 uint32(tx.TokenID), int64(tx.ToIdx)); err != nil {
1801 return tracerr.Wrap(err)
1802 }
1803 }
1804 c.CtlSetAddr(auction.Vars.BootCoordinator)
1805 for _, batch := range block.Rollup.Batches {
1806 if _, err := c.RollupForgeBatch(ð.RollupForgeBatchArgs{
1807 NewLastIdx: batch.Batch.LastIdx,
1808 NewStRoot: batch.Batch.StateRoot,
1809 NewExitRoot: batch.Batch.ExitRoot,
1810 L1CoordinatorTxs: batch.L1CoordinatorTxs,
1811 L1CoordinatorTxsAuths: [][]byte{}, // Intentionally empty
1812 L2TxsData: batch.L2Txs,
1813 FeeIdxCoordinator: batch.Batch.FeeIdxsCoordinator,
1814 // Circuit selector
1815 VerifierIdx: 0, // Intentionally empty
1816 L1Batch: batch.L1Batch,
1817 ProofA: [2]*big.Int{}, // Intentionally empty
1818 ProofB: [2][2]*big.Int{}, // Intentionally empty
1819 ProofC: [2]*big.Int{}, // Intentionally empty
1820 }); err != nil {
1821 return tracerr.Wrap(err)
1822 }
1823 }
1824 // Mine block and sync
1825 c.CtlMineBlock()
1826 }
1827 return nil
1828}