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