hermez-node/eth/rollup.go
eth/rollup.goRaw
1package eth
2
3import (
4 "context"
5 "fmt"
6 "math/big"
7 "strconv"
8 "strings"
9
10 "github.com/ethereum/go-ethereum"
11 "github.com/ethereum/go-ethereum/accounts/abi"
12 "github.com/ethereum/go-ethereum/accounts/abi/bind"
13 ethCommon "github.com/ethereum/go-ethereum/common"
14 "github.com/ethereum/go-ethereum/core/types"
15 "github.com/ethereum/go-ethereum/crypto"
16 "github.com/ethereum/go-ethereum/ethclient"
17 "github.com/hermeznetwork/hermez-node/common"
18 Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez"
19 HEZ "github.com/hermeznetwork/hermez-node/eth/contracts/tokenHEZ"
20 "github.com/hermeznetwork/hermez-node/log"
21 "github.com/hermeznetwork/tracerr"
22 "github.com/iden3/go-iden3-crypto/babyjub"
23)
24
25// QueueStruct is the queue of L1Txs for a batch
26type QueueStruct struct {
27 L1TxQueue []common.L1Tx
28 TotalL1TxFee *big.Int
29}
30
31// NewQueueStruct creates a new clear QueueStruct.
32func NewQueueStruct() *QueueStruct {
33 return &QueueStruct{
34 L1TxQueue: make([]common.L1Tx, 0),
35 TotalL1TxFee: big.NewInt(0),
36 }
37}
38
39// RollupState represents the state of the Rollup in the Smart Contract
40type RollupState struct {
41 StateRoot *big.Int
42 ExitRoots []*big.Int
43 // ExitNullifierMap map[[256 / 8]byte]bool
44 ExitNullifierMap map[int64]map[int64]bool // batchNum -> idx -> bool
45 TokenList []ethCommon.Address
46 TokenMap map[ethCommon.Address]bool
47 MapL1TxQueue map[int64]*QueueStruct
48 LastL1L2Batch int64
49 CurrentToForgeL1TxsNum int64
50 LastToForgeL1TxsNum int64
51 CurrentIdx int64
52}
53
54// RollupEventInitialize is the InitializeHermezEvent event of the
55// Smart Contract
56type RollupEventInitialize struct {
57 ForgeL1L2BatchTimeout uint8
58 FeeAddToken *big.Int
59 WithdrawalDelay uint64
60}
61
62// RollupVariables returns the RollupVariables from the initialize event
63func (ei *RollupEventInitialize) RollupVariables() *common.RollupVariables {
64 var buckets [common.RollupConstNumBuckets]common.BucketParams
65 for i := range buckets {
66 buckets[i] = common.BucketParams{
67 CeilUSD: big.NewInt(0),
68 Withdrawals: big.NewInt(0),
69 BlockWithdrawalRate: big.NewInt(0),
70 MaxWithdrawals: big.NewInt(0),
71 }
72 }
73 return &common.RollupVariables{
74 EthBlockNum: 0,
75 FeeAddToken: ei.FeeAddToken,
76 ForgeL1L2BatchTimeout: int64(ei.ForgeL1L2BatchTimeout),
77 WithdrawalDelay: ei.WithdrawalDelay,
78 Buckets: buckets,
79 SafeMode: false,
80 }
81}
82
83// RollupEventL1UserTx is an event of the Rollup Smart Contract
84type RollupEventL1UserTx struct {
85 // ToForgeL1TxsNum int64 // QueueIndex *big.Int
86 // Position int // TransactionIndex *big.Int
87 L1UserTx common.L1Tx
88}
89
90// RollupEventL1UserTxAux is an event of the Rollup Smart Contract
91type rollupEventL1UserTxAux struct {
92 ToForgeL1TxsNum uint64 // QueueIndex *big.Int
93 Position uint8 // TransactionIndex *big.Int
94 L1UserTx []byte
95}
96
97// RollupEventAddToken is an event of the Rollup Smart Contract
98type RollupEventAddToken struct {
99 TokenAddress ethCommon.Address
100 TokenID uint32
101}
102
103// RollupEventForgeBatch is an event of the Rollup Smart Contract
104type RollupEventForgeBatch struct {
105 BatchNum int64
106 // Sender ethCommon.Address
107 EthTxHash ethCommon.Hash
108 L1UserTxsLen uint16
109}
110
111// RollupEventUpdateForgeL1L2BatchTimeout is an event of the Rollup Smart Contract
112type RollupEventUpdateForgeL1L2BatchTimeout struct {
113 NewForgeL1L2BatchTimeout int64
114}
115
116// RollupEventUpdateFeeAddToken is an event of the Rollup Smart Contract
117type RollupEventUpdateFeeAddToken struct {
118 NewFeeAddToken *big.Int
119}
120
121// RollupEventWithdraw is an event of the Rollup Smart Contract
122type RollupEventWithdraw struct {
123 Idx uint64
124 NumExitRoot uint64
125 InstantWithdraw bool
126 TxHash ethCommon.Hash // Hash of the transaction that generated this event
127}
128
129type rollupEventUpdateBucketWithdrawAux struct {
130 NumBucket uint8
131 BlockStamp *big.Int
132 Withdrawals *big.Int
133}
134
135// RollupEventUpdateBucketWithdraw is an event of the Rollup Smart Contract
136type RollupEventUpdateBucketWithdraw struct {
137 NumBucket int
138 BlockStamp int64 // blockNum
139 Withdrawals *big.Int
140}
141
142// RollupEventUpdateWithdrawalDelay is an event of the Rollup Smart Contract
143type RollupEventUpdateWithdrawalDelay struct {
144 NewWithdrawalDelay uint64
145}
146
147// RollupUpdateBucketsParameters are the bucket parameters used in an update
148type RollupUpdateBucketsParameters struct {
149 CeilUSD *big.Int
150 Withdrawals *big.Int
151 BlockWithdrawalRate *big.Int
152 MaxWithdrawals *big.Int
153}
154
155type rollupEventUpdateBucketsParametersAux struct {
156 ArrayBuckets [common.RollupConstNumBuckets][4]*big.Int
157}
158
159// RollupEventUpdateBucketsParameters is an event of the Rollup Smart Contract
160type RollupEventUpdateBucketsParameters struct {
161 // ArrayBuckets [common.RollupConstNumBuckets][4]*big.Int
162 ArrayBuckets [common.RollupConstNumBuckets]RollupUpdateBucketsParameters
163 SafeMode bool
164}
165
166// RollupEventUpdateTokenExchange is an event of the Rollup Smart Contract
167type RollupEventUpdateTokenExchange struct {
168 AddressArray []ethCommon.Address
169 ValueArray []uint64
170}
171
172// RollupEventSafeMode is an event of the Rollup Smart Contract
173type RollupEventSafeMode struct {
174}
175
176// RollupEvents is the list of events in a block of the Rollup Smart Contract
177type RollupEvents struct {
178 L1UserTx []RollupEventL1UserTx
179 AddToken []RollupEventAddToken
180 ForgeBatch []RollupEventForgeBatch
181 UpdateForgeL1L2BatchTimeout []RollupEventUpdateForgeL1L2BatchTimeout
182 UpdateFeeAddToken []RollupEventUpdateFeeAddToken
183 Withdraw []RollupEventWithdraw
184 UpdateWithdrawalDelay []RollupEventUpdateWithdrawalDelay
185 UpdateBucketWithdraw []RollupEventUpdateBucketWithdraw
186 UpdateBucketsParameters []RollupEventUpdateBucketsParameters
187 UpdateTokenExchange []RollupEventUpdateTokenExchange
188 SafeMode []RollupEventSafeMode
189}
190
191// NewRollupEvents creates an empty RollupEvents with the slices initialized.
192func NewRollupEvents() RollupEvents {
193 return RollupEvents{
194 L1UserTx: make([]RollupEventL1UserTx, 0),
195 AddToken: make([]RollupEventAddToken, 0),
196 ForgeBatch: make([]RollupEventForgeBatch, 0),
197 UpdateForgeL1L2BatchTimeout: make([]RollupEventUpdateForgeL1L2BatchTimeout, 0),
198 UpdateFeeAddToken: make([]RollupEventUpdateFeeAddToken, 0),
199 Withdraw: make([]RollupEventWithdraw, 0),
200 }
201}
202
203// RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
204type RollupForgeBatchArgs struct {
205 NewLastIdx int64
206 NewStRoot *big.Int
207 NewExitRoot *big.Int
208 L1UserTxs []common.L1Tx
209 L1CoordinatorTxs []common.L1Tx
210 L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx
211 L2TxsData []common.L2Tx
212 FeeIdxCoordinator []common.Idx
213 // Circuit selector
214 VerifierIdx uint8
215 L1Batch bool
216 ProofA [2]*big.Int
217 ProofB [2][2]*big.Int
218 ProofC [2]*big.Int
219}
220
221// RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract
222type rollupForgeBatchArgsAux struct {
223 NewLastIdx *big.Int
224 NewStRoot *big.Int
225 NewExitRoot *big.Int
226 EncodedL1CoordinatorTx []byte
227 L1L2TxsData []byte
228 FeeIdxCoordinator []byte
229 // Circuit selector
230 VerifierIdx uint8
231 L1Batch bool
232 ProofA [2]*big.Int
233 ProofB [2][2]*big.Int
234 ProofC [2]*big.Int
235}
236
237// RollupInterface is the inteface to to Rollup Smart Contract
238type RollupInterface interface {
239 //
240 // Smart Contract Methods
241 //
242
243 // Public Functions
244
245 RollupForgeBatch(*RollupForgeBatchArgs, *bind.TransactOpts) (*types.Transaction, error)
246 RollupAddToken(tokenAddress ethCommon.Address, feeAddToken,
247 deadline *big.Int) (*types.Transaction, error)
248
249 RollupWithdrawMerkleProof(babyPubKey babyjub.PublicKeyComp, tokenID uint32, numExitRoot,
250 idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction,
251 error)
252 RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int, tokenID uint32,
253 numExitRoot, idx int64, amount *big.Int, instantWithdraw bool) (*types.Transaction, error)
254
255 RollupL1UserTxERC20ETH(fromBJJ babyjub.PublicKeyComp, fromIdx int64, depositAmount *big.Int,
256 amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error)
257 RollupL1UserTxERC20Permit(fromBJJ babyjub.PublicKeyComp, fromIdx int64,
258 depositAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64,
259 deadline *big.Int) (tx *types.Transaction, err error)
260
261 // Governance Public Functions
262 RollupUpdateForgeL1L2BatchTimeout(newForgeL1L2BatchTimeout int64) (*types.Transaction, error)
263 RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error)
264
265 // Viewers
266 RollupRegisterTokensCount() (*big.Int, error)
267 RollupLastForgedBatch() (int64, error)
268
269 //
270 // Smart Contract Status
271 //
272
273 RollupConstants() (*common.RollupConstants, error)
274 RollupEventsByBlock(blockNum int64, blockHash *ethCommon.Hash) (*RollupEvents, error)
275 RollupForgeBatchArgs(ethCommon.Hash, uint16) (*RollupForgeBatchArgs, *ethCommon.Address, error)
276 RollupEventInit() (*RollupEventInitialize, int64, error)
277}
278
279//
280// Implementation
281//
282
283// RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum.
284type RollupClient struct {
285 client *EthereumClient
286 chainID *big.Int
287 address ethCommon.Address
288 tokenHEZCfg TokenConfig
289 hermez *Hermez.Hermez
290 tokenHEZ *HEZ.HEZ
291 contractAbi abi.ABI
292 opts *bind.CallOpts
293 consts *common.RollupConstants
294}
295
296// NewRollupClient creates a new RollupClient
297func NewRollupClient(client *EthereumClient, address ethCommon.Address,
298 tokenHEZCfg TokenConfig) (*RollupClient, error) {
299 contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI)))
300 if err != nil {
301 return nil, tracerr.Wrap(err)
302 }
303 hermez, err := Hermez.NewHermez(address, client.Client())
304 if err != nil {
305 return nil, tracerr.Wrap(err)
306 }
307 tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
308 if err != nil {
309 return nil, tracerr.Wrap(err)
310 }
311 chainID, err := client.EthChainID()
312 if err != nil {
313 return nil, tracerr.Wrap(err)
314 }
315 c := &RollupClient{
316 client: client,
317 chainID: chainID,
318 address: address,
319 tokenHEZCfg: tokenHEZCfg,
320 hermez: hermez,
321 tokenHEZ: tokenHEZ,
322 contractAbi: contractAbi,
323 opts: newCallOpts(),
324 }
325 consts, err := c.RollupConstants()
326 if err != nil {
327 return nil, tracerr.Wrap(fmt.Errorf("RollupConstants at %v: %w", address, err))
328 }
329 c.consts = consts
330 return c, nil
331}
332
333// RollupForgeBatch is the interface to call the smart contract function
334func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs,
335 auth *bind.TransactOpts) (tx *types.Transaction, err error) {
336 if auth == nil {
337 auth, err = c.client.NewAuth()
338 if err != nil {
339 return nil, tracerr.Wrap(err)
340 }
341 auth.GasLimit = 1000000
342 }
343
344 nLevels := c.consts.Verifiers[args.VerifierIdx].NLevels
345 lenBytes := nLevels / 8 //nolint:gomnd
346 newLastIdx := big.NewInt(int64(args.NewLastIdx))
347 // L1CoordinatorBytes
348 var l1CoordinatorBytes []byte
349 for i := 0; i < len(args.L1CoordinatorTxs); i++ {
350 l1 := args.L1CoordinatorTxs[i]
351 bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i])
352 if err != nil {
353 return nil, tracerr.Wrap(err)
354 }
355 l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...)
356 }
357 // L1L2TxData
358 var l1l2TxData []byte
359 for i := 0; i < len(args.L1UserTxs); i++ {
360 l1User := args.L1UserTxs[i]
361 bytesl1User, err := l1User.BytesDataAvailability(uint32(nLevels))
362 if err != nil {
363 return nil, tracerr.Wrap(err)
364 }
365 l1l2TxData = append(l1l2TxData, bytesl1User[:]...)
366 }
367 for i := 0; i < len(args.L1CoordinatorTxs); i++ {
368 l1Coord := args.L1CoordinatorTxs[i]
369 bytesl1Coord, err := l1Coord.BytesDataAvailability(uint32(nLevels))
370 if err != nil {
371 return nil, tracerr.Wrap(err)
372 }
373 l1l2TxData = append(l1l2TxData, bytesl1Coord[:]...)
374 }
375 for i := 0; i < len(args.L2TxsData); i++ {
376 l2 := args.L2TxsData[i]
377 bytesl2, err := l2.BytesDataAvailability(uint32(nLevels))
378 if err != nil {
379 return nil, tracerr.Wrap(err)
380 }
381 l1l2TxData = append(l1l2TxData, bytesl2[:]...)
382 }
383 // FeeIdxCoordinator
384 var feeIdxCoordinator []byte
385 if len(args.FeeIdxCoordinator) > common.RollupConstMaxFeeIdxCoordinator {
386 return nil, tracerr.Wrap(fmt.Errorf("len(args.FeeIdxCoordinator) > %v",
387 common.RollupConstMaxFeeIdxCoordinator))
388 }
389 for i := 0; i < common.RollupConstMaxFeeIdxCoordinator; i++ {
390 feeIdx := common.Idx(0)
391 if i < len(args.FeeIdxCoordinator) {
392 feeIdx = args.FeeIdxCoordinator[i]
393 }
394 bytesFeeIdx, err := feeIdx.Bytes()
395 if err != nil {
396 return nil, tracerr.Wrap(err)
397 }
398 feeIdxCoordinator = append(feeIdxCoordinator,
399 bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...)
400 }
401 tx, err = c.hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot,
402 l1CoordinatorBytes, l1l2TxData, feeIdxCoordinator, args.VerifierIdx, args.L1Batch,
403 args.ProofA, args.ProofB, args.ProofC)
404 if err != nil {
405 return nil, tracerr.Wrap(fmt.Errorf("Hermez.ForgeBatch: %w", err))
406 }
407 return tx, nil
408}
409
410// RollupAddToken is the interface to call the smart contract function.
411// `feeAddToken` is the amount of HEZ tokens that will be paid to add the
412// token. `feeAddToken` must match the public value of the smart contract.
413func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken,
414 deadline *big.Int) (tx *types.Transaction, err error) {
415 if tx, err = c.client.CallAuth(
416 0,
417 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
418 owner := c.client.account.Address
419 spender := c.address
420 nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
421 if err != nil {
422 return nil, tracerr.Wrap(err)
423 }
424 tokenName := c.tokenHEZCfg.Name
425 tokenAddr := c.tokenHEZCfg.Address
426 digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID,
427 feeAddToken, nonce, deadline, tokenName)
428 signature, _ := c.client.ks.SignHash(*c.client.account, digest)
429 permit := createPermit(owner, spender, feeAddToken, deadline, digest,
430 signature)
431
432 return c.hermez.AddToken(auth, tokenAddress, permit)
433 },
434 ); err != nil {
435 return nil, tracerr.Wrap(fmt.Errorf("Failed add Token %w", err))
436 }
437 return tx, nil
438}
439
440// RollupWithdrawMerkleProof is the interface to call the smart contract function
441func (c *RollupClient) RollupWithdrawMerkleProof(fromBJJ babyjub.PublicKeyComp, tokenID uint32,
442 numExitRoot, idx int64, amount *big.Int, siblings []*big.Int,
443 instantWithdraw bool) (tx *types.Transaction, err error) {
444 if tx, err = c.client.CallAuth(
445 0,
446 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
447 pkCompB := common.SwapEndianness(fromBJJ[:])
448 babyPubKey := new(big.Int).SetBytes(pkCompB)
449 numExitRootB := uint32(numExitRoot)
450 idxBig := big.NewInt(idx)
451 return c.hermez.WithdrawMerkleProof(auth, tokenID, amount, babyPubKey,
452 numExitRootB, siblings, idxBig, instantWithdraw)
453 },
454 ); err != nil {
455 return nil, tracerr.Wrap(fmt.Errorf("Failed update WithdrawMerkleProof: %w", err))
456 }
457 return tx, nil
458}
459
460// RollupWithdrawCircuit is the interface to call the smart contract function
461func (c *RollupClient) RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int,
462 tokenID uint32, numExitRoot, idx int64, amount *big.Int, instantWithdraw bool) (*types.Transaction,
463 error) {
464 log.Error("TODO")
465 return nil, tracerr.Wrap(errTODO)
466}
467
468// RollupL1UserTxERC20ETH is the interface to call the smart contract function
469func (c *RollupClient) RollupL1UserTxERC20ETH(fromBJJ babyjub.PublicKeyComp, fromIdx int64,
470 depositAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (tx *types.Transaction,
471 err error) {
472 if tx, err = c.client.CallAuth(
473 0,
474 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
475 var babyPubKey *big.Int
476 if fromBJJ != common.EmptyBJJComp {
477 pkCompB := common.SwapEndianness(fromBJJ[:])
478 babyPubKey = new(big.Int).SetBytes(pkCompB)
479 } else {
480 babyPubKey = big.NewInt(0)
481 }
482 fromIdxBig := big.NewInt(fromIdx)
483 toIdxBig := big.NewInt(toIdx)
484 depositAmountF, err := common.NewFloat40(depositAmount)
485 if err != nil {
486 return nil, tracerr.Wrap(err)
487 }
488 amountF, err := common.NewFloat40(amount)
489 if err != nil {
490 return nil, tracerr.Wrap(err)
491 }
492 if tokenID == 0 {
493 auth.Value = depositAmount
494 }
495 var permit []byte
496 return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig, uint16(depositAmountF),
497 uint16(amountF), tokenID, toIdxBig, permit)
498 },
499 ); err != nil {
500 return nil, tracerr.Wrap(fmt.Errorf("Failed add L1 Tx ERC20/ETH: %w", err))
501 }
502 return tx, nil
503}
504
505// RollupL1UserTxERC20Permit is the interface to call the smart contract function
506func (c *RollupClient) RollupL1UserTxERC20Permit(fromBJJ babyjub.PublicKeyComp, fromIdx int64,
507 depositAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64,
508 deadline *big.Int) (tx *types.Transaction, err error) {
509 if tx, err = c.client.CallAuth(
510 0,
511 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
512 var babyPubKey *big.Int
513 if fromBJJ != common.EmptyBJJComp {
514 pkCompB := common.SwapEndianness(fromBJJ[:])
515 babyPubKey = new(big.Int).SetBytes(pkCompB)
516 } else {
517 babyPubKey = big.NewInt(0)
518 }
519 fromIdxBig := big.NewInt(fromIdx)
520 toIdxBig := big.NewInt(toIdx)
521 depositAmountF, err := common.NewFloat40(depositAmount)
522 if err != nil {
523 return nil, tracerr.Wrap(err)
524 }
525 amountF, err := common.NewFloat40(amount)
526 if err != nil {
527 return nil, tracerr.Wrap(err)
528 }
529 if tokenID == 0 {
530 auth.Value = depositAmount
531 }
532 owner := c.client.account.Address
533 spender := c.address
534 nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
535 if err != nil {
536 return nil, tracerr.Wrap(err)
537 }
538 tokenName := c.tokenHEZCfg.Name
539 tokenAddr := c.tokenHEZCfg.Address
540 digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID,
541 amount, nonce, deadline, tokenName)
542 signature, _ := c.client.ks.SignHash(*c.client.account, digest)
543 permit := createPermit(owner, spender, amount, deadline, digest, signature)
544 return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig,
545 uint16(depositAmountF), uint16(amountF), tokenID, toIdxBig, permit)
546 },
547 ); err != nil {
548 return nil, tracerr.Wrap(fmt.Errorf("Failed add L1 Tx ERC20Permit: %w", err))
549 }
550 return tx, nil
551}
552
553// RollupRegisterTokensCount is the interface to call the smart contract function
554func (c *RollupClient) RollupRegisterTokensCount() (registerTokensCount *big.Int, err error) {
555 if err := c.client.Call(func(ec *ethclient.Client) error {
556 registerTokensCount, err = c.hermez.RegisterTokensCount(c.opts)
557 return tracerr.Wrap(err)
558 }); err != nil {
559 return nil, tracerr.Wrap(err)
560 }
561 return registerTokensCount, nil
562}
563
564// RollupLastForgedBatch is the interface to call the smart contract function
565func (c *RollupClient) RollupLastForgedBatch() (lastForgedBatch int64, err error) {
566 if err := c.client.Call(func(ec *ethclient.Client) error {
567 _lastForgedBatch, err := c.hermez.LastForgedBatch(c.opts)
568 lastForgedBatch = int64(_lastForgedBatch)
569 return tracerr.Wrap(err)
570 }); err != nil {
571 return 0, tracerr.Wrap(err)
572 }
573 return lastForgedBatch, nil
574}
575
576// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
577func (c *RollupClient) RollupUpdateForgeL1L2BatchTimeout(
578 newForgeL1L2BatchTimeout int64) (tx *types.Transaction, err error) {
579 if tx, err = c.client.CallAuth(
580 0,
581 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
582 return c.hermez.UpdateForgeL1L2BatchTimeout(auth,
583 uint8(newForgeL1L2BatchTimeout))
584 },
585 ); err != nil {
586 return nil, tracerr.Wrap(fmt.Errorf("Failed update ForgeL1L2BatchTimeout: %w", err))
587 }
588 return tx, nil
589}
590
591// RollupUpdateFeeAddToken is the interface to call the smart contract function
592func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction,
593 err error) {
594 if tx, err = c.client.CallAuth(
595 0,
596 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
597 return c.hermez.UpdateFeeAddToken(auth, newFeeAddToken)
598 },
599 ); err != nil {
600 return nil, tracerr.Wrap(fmt.Errorf("Failed update FeeAddToken: %w", err))
601 }
602 return tx, nil
603}
604
605// RollupUpdateBucketsParameters is the interface to call the smart contract function
606func (c *RollupClient) RollupUpdateBucketsParameters(
607 arrayBuckets [common.RollupConstNumBuckets]RollupUpdateBucketsParameters,
608) (tx *types.Transaction, err error) {
609 params := [common.RollupConstNumBuckets][4]*big.Int{}
610 for i, bucket := range arrayBuckets {
611 params[i][0] = bucket.CeilUSD
612 params[i][1] = bucket.Withdrawals
613 params[i][2] = bucket.BlockWithdrawalRate
614 params[i][3] = bucket.MaxWithdrawals
615 }
616 if tx, err = c.client.CallAuth(
617 12500000, //nolint:gomnd
618 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
619 return c.hermez.UpdateBucketsParameters(auth, params)
620 },
621 ); err != nil {
622 return nil, tracerr.Wrap(fmt.Errorf("Failed update Buckets Parameters: %w", err))
623 }
624 return tx, nil
625}
626
627// RollupUpdateTokenExchange is the interface to call the smart contract function
628func (c *RollupClient) RollupUpdateTokenExchange(addressArray []ethCommon.Address,
629 valueArray []uint64) (tx *types.Transaction, err error) {
630 if tx, err = c.client.CallAuth(
631 0,
632 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
633 return c.hermez.UpdateTokenExchange(auth, addressArray, valueArray)
634 },
635 ); err != nil {
636 return nil, tracerr.Wrap(fmt.Errorf("Failed update Token Exchange: %w", err))
637 }
638 return tx, nil
639}
640
641// RollupUpdateWithdrawalDelay is the interface to call the smart contract function
642func (c *RollupClient) RollupUpdateWithdrawalDelay(newWithdrawalDelay int64) (tx *types.Transaction,
643 err error) {
644 if tx, err = c.client.CallAuth(
645 0,
646 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
647 return c.hermez.UpdateWithdrawalDelay(auth, uint64(newWithdrawalDelay))
648 },
649 ); err != nil {
650 return nil, tracerr.Wrap(fmt.Errorf("Failed update WithdrawalDelay: %w", err))
651 }
652 return tx, nil
653}
654
655// RollupSafeMode is the interface to call the smart contract function
656func (c *RollupClient) RollupSafeMode() (tx *types.Transaction, err error) {
657 if tx, err = c.client.CallAuth(
658 0,
659 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
660 return c.hermez.SafeMode(auth)
661 },
662 ); err != nil {
663 return nil, tracerr.Wrap(fmt.Errorf("Failed update Safe Mode: %w", err))
664 }
665 return tx, nil
666}
667
668// RollupInstantWithdrawalViewer is the interface to call the smart contract function
669func (c *RollupClient) RollupInstantWithdrawalViewer(tokenAddress ethCommon.Address,
670 amount *big.Int) (instantAllowed bool, err error) {
671 if err := c.client.Call(func(ec *ethclient.Client) error {
672 instantAllowed, err = c.hermez.InstantWithdrawalViewer(c.opts, tokenAddress, amount)
673 return tracerr.Wrap(err)
674 }); err != nil {
675 return false, tracerr.Wrap(err)
676 }
677 return instantAllowed, nil
678}
679
680// RollupConstants returns the Constants of the Rollup Smart Contract
681func (c *RollupClient) RollupConstants() (rollupConstants *common.RollupConstants, err error) {
682 rollupConstants = new(common.RollupConstants)
683 if err := c.client.Call(func(ec *ethclient.Client) error {
684 absoluteMaxL1L2BatchTimeout, err := c.hermez.ABSOLUTEMAXL1L2BATCHTIMEOUT(c.opts)
685 if err != nil {
686 return tracerr.Wrap(err)
687 }
688 rollupConstants.AbsoluteMaxL1L2BatchTimeout = int64(absoluteMaxL1L2BatchTimeout)
689 rollupConstants.TokenHEZ, err = c.hermez.TokenHEZ(c.opts)
690 if err != nil {
691 return tracerr.Wrap(err)
692 }
693 rollupVerifiersLength, err := c.hermez.RollupVerifiersLength(c.opts)
694 if err != nil {
695 return tracerr.Wrap(err)
696 }
697 for i := int64(0); i < rollupVerifiersLength.Int64(); i++ {
698 var newRollupVerifier common.RollupVerifierStruct
699 rollupVerifier, err := c.hermez.RollupVerifiers(c.opts, big.NewInt(i))
700 if err != nil {
701 return tracerr.Wrap(err)
702 }
703 newRollupVerifier.MaxTx = rollupVerifier.MaxTx.Int64()
704 newRollupVerifier.NLevels = rollupVerifier.NLevels.Int64()
705 rollupConstants.Verifiers = append(rollupConstants.Verifiers,
706 newRollupVerifier)
707 }
708 rollupConstants.HermezAuctionContract, err = c.hermez.HermezAuctionContract(c.opts)
709 if err != nil {
710 return tracerr.Wrap(err)
711 }
712 rollupConstants.HermezGovernanceAddress, err = c.hermez.HermezGovernanceAddress(c.opts)
713 if err != nil {
714 return tracerr.Wrap(err)
715 }
716 rollupConstants.WithdrawDelayerContract, err = c.hermez.WithdrawDelayerContract(c.opts)
717 return tracerr.Wrap(err)
718 }); err != nil {
719 return nil, tracerr.Wrap(err)
720 }
721 return rollupConstants, nil
722}
723
724var (
725 logHermezL1UserTxEvent = crypto.Keccak256Hash([]byte(
726 "L1UserTxEvent(uint32,uint8,bytes)"))
727 logHermezAddToken = crypto.Keccak256Hash([]byte(
728 "AddToken(address,uint32)"))
729 logHermezForgeBatch = crypto.Keccak256Hash([]byte(
730 "ForgeBatch(uint32,uint16)"))
731 logHermezUpdateForgeL1L2BatchTimeout = crypto.Keccak256Hash([]byte(
732 "UpdateForgeL1L2BatchTimeout(uint8)"))
733 logHermezUpdateFeeAddToken = crypto.Keccak256Hash([]byte(
734 "UpdateFeeAddToken(uint256)"))
735 logHermezWithdrawEvent = crypto.Keccak256Hash([]byte(
736 "WithdrawEvent(uint48,uint32,bool)"))
737 logHermezUpdateBucketWithdraw = crypto.Keccak256Hash([]byte(
738 "UpdateBucketWithdraw(uint8,uint256,uint256)"))
739 logHermezUpdateWithdrawalDelay = crypto.Keccak256Hash([]byte(
740 "UpdateWithdrawalDelay(uint64)"))
741 logHermezUpdateBucketsParameters = crypto.Keccak256Hash([]byte(
742 "UpdateBucketsParameters(uint256[4][" + strconv.Itoa(common.RollupConstNumBuckets) + "])"))
743 logHermezUpdateTokenExchange = crypto.Keccak256Hash([]byte(
744 "UpdateTokenExchange(address[],uint64[])"))
745 logHermezSafeMode = crypto.Keccak256Hash([]byte(
746 "SafeMode()"))
747 logHermezInitialize = crypto.Keccak256Hash([]byte(
748 "InitializeHermezEvent(uint8,uint256,uint64)"))
749)
750
751// RollupEventInit returns the initialize event with its corresponding block number
752func (c *RollupClient) RollupEventInit() (*RollupEventInitialize, int64, error) {
753 query := ethereum.FilterQuery{
754 Addresses: []ethCommon.Address{
755 c.address,
756 },
757 Topics: [][]ethCommon.Hash{{logHermezInitialize}},
758 }
759 logs, err := c.client.client.FilterLogs(context.Background(), query)
760 if err != nil {
761 return nil, 0, tracerr.Wrap(err)
762 }
763 if len(logs) != 1 {
764 return nil, 0, tracerr.Wrap(fmt.Errorf("no event of type InitializeHermezEvent found"))
765 }
766 vLog := logs[0]
767 if vLog.Topics[0] != logHermezInitialize {
768 return nil, 0, tracerr.Wrap(fmt.Errorf("event is not InitializeHermezEvent"))
769 }
770
771 var rollupInit RollupEventInitialize
772 if err := c.contractAbi.UnpackIntoInterface(&rollupInit, "InitializeHermezEvent",
773 vLog.Data); err != nil {
774 return nil, 0, tracerr.Wrap(err)
775 }
776 return &rollupInit, int64(vLog.BlockNumber), tracerr.Wrap(err)
777}
778
779// RollupEventsByBlock returns the events in a block that happened in the
780// Rollup Smart Contract.
781// To query by blockNum, set blockNum >= 0 and blockHash == nil.
782// To query by blockHash set blockHash != nil, and blockNum will be ignored.
783// If there are no events in that block the result is nil.
784func (c *RollupClient) RollupEventsByBlock(blockNum int64,
785 blockHash *ethCommon.Hash) (*RollupEvents, error) {
786 var rollupEvents RollupEvents
787
788 var blockNumBigInt *big.Int
789 if blockHash == nil {
790 blockNumBigInt = big.NewInt(blockNum)
791 }
792 query := ethereum.FilterQuery{
793 BlockHash: blockHash,
794 FromBlock: blockNumBigInt,
795 ToBlock: blockNumBigInt,
796 Addresses: []ethCommon.Address{
797 c.address,
798 },
799 Topics: [][]ethCommon.Hash{},
800 }
801 logs, err := c.client.client.FilterLogs(context.Background(), query)
802 if err != nil {
803 return nil, tracerr.Wrap(err)
804 }
805 if len(logs) == 0 {
806 return nil, nil
807 }
808
809 for _, vLog := range logs {
810 if blockHash != nil && vLog.BlockHash != *blockHash {
811 log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
812 return nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
813 }
814 switch vLog.Topics[0] {
815 case logHermezL1UserTxEvent:
816 var L1UserTxAux rollupEventL1UserTxAux
817 var L1UserTx RollupEventL1UserTx
818 err := c.contractAbi.UnpackIntoInterface(&L1UserTxAux, "L1UserTxEvent", vLog.Data)
819 if err != nil {
820 return nil, tracerr.Wrap(err)
821 }
822 L1Tx, err := common.L1UserTxFromBytes(L1UserTxAux.L1UserTx)
823 if err != nil {
824 return nil, tracerr.Wrap(err)
825 }
826 toForgeL1TxsNum := new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
827 L1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum
828 L1Tx.Position = int(new(big.Int).SetBytes(vLog.Topics[2][:]).Int64())
829 L1Tx.UserOrigin = true
830 L1UserTx.L1UserTx = *L1Tx
831 rollupEvents.L1UserTx = append(rollupEvents.L1UserTx, L1UserTx)
832 case logHermezAddToken:
833 var addToken RollupEventAddToken
834 err := c.contractAbi.UnpackIntoInterface(&addToken, "AddToken", vLog.Data)
835 if err != nil {
836 return nil, tracerr.Wrap(err)
837 }
838 addToken.TokenAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
839 rollupEvents.AddToken = append(rollupEvents.AddToken, addToken)
840 case logHermezForgeBatch:
841 var forgeBatch RollupEventForgeBatch
842 err := c.contractAbi.UnpackIntoInterface(&forgeBatch, "ForgeBatch", vLog.Data)
843 if err != nil {
844 return nil, tracerr.Wrap(err)
845 }
846 forgeBatch.BatchNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
847 forgeBatch.EthTxHash = vLog.TxHash
848 // forgeBatch.Sender = vLog.Address
849 rollupEvents.ForgeBatch = append(rollupEvents.ForgeBatch, forgeBatch)
850 case logHermezUpdateForgeL1L2BatchTimeout:
851 var updateForgeL1L2BatchTimeout struct {
852 NewForgeL1L2BatchTimeout uint8
853 }
854 err := c.contractAbi.UnpackIntoInterface(&updateForgeL1L2BatchTimeout,
855 "UpdateForgeL1L2BatchTimeout", vLog.Data)
856 if err != nil {
857 return nil, tracerr.Wrap(err)
858 }
859 rollupEvents.UpdateForgeL1L2BatchTimeout = append(rollupEvents.UpdateForgeL1L2BatchTimeout,
860 RollupEventUpdateForgeL1L2BatchTimeout{
861 NewForgeL1L2BatchTimeout: int64(updateForgeL1L2BatchTimeout.NewForgeL1L2BatchTimeout),
862 })
863 case logHermezUpdateFeeAddToken:
864 var updateFeeAddToken RollupEventUpdateFeeAddToken
865 err := c.contractAbi.UnpackIntoInterface(&updateFeeAddToken, "UpdateFeeAddToken", vLog.Data)
866 if err != nil {
867 return nil, tracerr.Wrap(err)
868 }
869 rollupEvents.UpdateFeeAddToken = append(rollupEvents.UpdateFeeAddToken, updateFeeAddToken)
870 case logHermezWithdrawEvent:
871 var withdraw RollupEventWithdraw
872 withdraw.Idx = new(big.Int).SetBytes(vLog.Topics[1][:]).Uint64()
873 withdraw.NumExitRoot = new(big.Int).SetBytes(vLog.Topics[2][:]).Uint64()
874 instantWithdraw := new(big.Int).SetBytes(vLog.Topics[3][:]).Uint64()
875 if instantWithdraw == 1 {
876 withdraw.InstantWithdraw = true
877 }
878 withdraw.TxHash = vLog.TxHash
879 rollupEvents.Withdraw = append(rollupEvents.Withdraw, withdraw)
880 case logHermezUpdateBucketWithdraw:
881 var updateBucketWithdrawAux rollupEventUpdateBucketWithdrawAux
882 var updateBucketWithdraw RollupEventUpdateBucketWithdraw
883 err := c.contractAbi.UnpackIntoInterface(&updateBucketWithdrawAux,
884 "UpdateBucketWithdraw", vLog.Data)
885 if err != nil {
886 return nil, tracerr.Wrap(err)
887 }
888 updateBucketWithdraw.Withdrawals = updateBucketWithdrawAux.Withdrawals
889 updateBucketWithdraw.NumBucket = int(new(big.Int).SetBytes(vLog.Topics[1][:]).Int64())
890 updateBucketWithdraw.BlockStamp = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
891 rollupEvents.UpdateBucketWithdraw =
892 append(rollupEvents.UpdateBucketWithdraw, updateBucketWithdraw)
893
894 case logHermezUpdateWithdrawalDelay:
895 var withdrawalDelay RollupEventUpdateWithdrawalDelay
896 err := c.contractAbi.UnpackIntoInterface(&withdrawalDelay, "UpdateWithdrawalDelay", vLog.Data)
897 if err != nil {
898 return nil, tracerr.Wrap(err)
899 }
900 rollupEvents.UpdateWithdrawalDelay = append(rollupEvents.UpdateWithdrawalDelay, withdrawalDelay)
901 case logHermezUpdateBucketsParameters:
902 var bucketsParametersAux rollupEventUpdateBucketsParametersAux
903 var bucketsParameters RollupEventUpdateBucketsParameters
904 err := c.contractAbi.UnpackIntoInterface(&bucketsParametersAux,
905 "UpdateBucketsParameters", vLog.Data)
906 if err != nil {
907 return nil, tracerr.Wrap(err)
908 }
909 for i, bucket := range bucketsParametersAux.ArrayBuckets {
910 bucketsParameters.ArrayBuckets[i].CeilUSD = bucket[0]
911 bucketsParameters.ArrayBuckets[i].Withdrawals = bucket[1]
912 bucketsParameters.ArrayBuckets[i].BlockWithdrawalRate = bucket[2]
913 bucketsParameters.ArrayBuckets[i].MaxWithdrawals = bucket[3]
914 }
915 rollupEvents.UpdateBucketsParameters =
916 append(rollupEvents.UpdateBucketsParameters, bucketsParameters)
917 case logHermezUpdateTokenExchange:
918 var tokensExchange RollupEventUpdateTokenExchange
919 err := c.contractAbi.UnpackIntoInterface(&tokensExchange, "UpdateTokenExchange", vLog.Data)
920 if err != nil {
921 return nil, tracerr.Wrap(err)
922 }
923 rollupEvents.UpdateTokenExchange = append(rollupEvents.UpdateTokenExchange, tokensExchange)
924 case logHermezSafeMode:
925 var safeMode RollupEventSafeMode
926 rollupEvents.SafeMode = append(rollupEvents.SafeMode, safeMode)
927 // Also add an UpdateBucketsParameter with
928 // SafeMode=true to keep the order between `safeMode`
929 // and `UpdateBucketsParameters`
930 bucketsParameters := RollupEventUpdateBucketsParameters{
931 SafeMode: true,
932 }
933 for i := range bucketsParameters.ArrayBuckets {
934 bucketsParameters.ArrayBuckets[i].CeilUSD = big.NewInt(0)
935 bucketsParameters.ArrayBuckets[i].Withdrawals = big.NewInt(0)
936 bucketsParameters.ArrayBuckets[i].BlockWithdrawalRate = big.NewInt(0)
937 bucketsParameters.ArrayBuckets[i].MaxWithdrawals = big.NewInt(0)
938 }
939 rollupEvents.UpdateBucketsParameters = append(rollupEvents.UpdateBucketsParameters,
940 bucketsParameters)
941 }
942 }
943 return &rollupEvents, nil
944}
945
946// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the
947// Rollup Smart Contract in the given transaction, and the sender address.
948func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash,
949 l1UserTxsLen uint16) (*RollupForgeBatchArgs, *ethCommon.Address, error) {
950 tx, _, err := c.client.client.TransactionByHash(context.Background(), ethTxHash)
951 if err != nil {
952 return nil, nil, tracerr.Wrap(fmt.Errorf("TransactionByHash: %w", err))
953 }
954 txData := tx.Data()
955
956 method, err := c.contractAbi.MethodById(txData[:4])
957 if err != nil {
958 return nil, nil, tracerr.Wrap(err)
959 }
960 receipt, err := c.client.client.TransactionReceipt(context.Background(), ethTxHash)
961 if err != nil {
962 return nil, nil, tracerr.Wrap(err)
963 }
964 sender, err := c.client.client.TransactionSender(context.Background(), tx,
965 receipt.Logs[0].BlockHash, receipt.Logs[0].Index)
966 if err != nil {
967 return nil, nil, tracerr.Wrap(err)
968 }
969 var aux rollupForgeBatchArgsAux
970 if values, err := method.Inputs.Unpack(txData[4:]); err != nil {
971 return nil, nil, tracerr.Wrap(err)
972 } else if err := method.Inputs.Copy(&aux, values); err != nil {
973 return nil, nil, tracerr.Wrap(err)
974 }
975 rollupForgeBatchArgs := RollupForgeBatchArgs{
976 L1Batch: aux.L1Batch,
977 NewExitRoot: aux.NewExitRoot,
978 NewLastIdx: aux.NewLastIdx.Int64(),
979 NewStRoot: aux.NewStRoot,
980 ProofA: aux.ProofA,
981 ProofB: aux.ProofB,
982 ProofC: aux.ProofC,
983 VerifierIdx: aux.VerifierIdx,
984 L1CoordinatorTxs: []common.L1Tx{},
985 L1CoordinatorTxsAuths: [][]byte{},
986 L2TxsData: []common.L2Tx{},
987 FeeIdxCoordinator: []common.Idx{},
988 }
989 nLevels := c.consts.Verifiers[rollupForgeBatchArgs.VerifierIdx].NLevels
990 lenL1L2TxsBytes := int((nLevels/8)*2 + common.Float40BytesLength + 1) //nolint:gomnd
991 numBytesL1TxUser := int(l1UserTxsLen) * lenL1L2TxsBytes
992 numTxsL1Coord := len(aux.EncodedL1CoordinatorTx) / common.RollupConstL1CoordinatorTotalBytes
993 numBytesL1TxCoord := numTxsL1Coord * lenL1L2TxsBytes
994 numBeginL2Tx := numBytesL1TxCoord + numBytesL1TxUser
995 l1UserTxsData := []byte{}
996 if l1UserTxsLen > 0 {
997 l1UserTxsData = aux.L1L2TxsData[:numBytesL1TxUser]
998 }
999 for i := 0; i < int(l1UserTxsLen); i++ {
1000 l1Tx, err :=
1001 common.L1TxFromDataAvailability(l1UserTxsData[i*lenL1L2TxsBytes:(i+1)*lenL1L2TxsBytes],
1002 uint32(nLevels))
1003 if err != nil {
1004 return nil, nil, tracerr.Wrap(err)
1005 }
1006 rollupForgeBatchArgs.L1UserTxs = append(rollupForgeBatchArgs.L1UserTxs, *l1Tx)
1007 }
1008 l2TxsData := []byte{}
1009 if numBeginL2Tx < len(aux.L1L2TxsData) {
1010 l2TxsData = aux.L1L2TxsData[numBeginL2Tx:]
1011 }
1012 numTxsL2 := len(l2TxsData) / lenL1L2TxsBytes
1013 for i := 0; i < numTxsL2; i++ {
1014 l2Tx, err :=
1015 common.L2TxFromBytesDataAvailability(l2TxsData[i*lenL1L2TxsBytes:(i+1)*lenL1L2TxsBytes],
1016 int(nLevels))
1017 if err != nil {
1018 return nil, nil, tracerr.Wrap(err)
1019 }
1020 rollupForgeBatchArgs.L2TxsData = append(rollupForgeBatchArgs.L2TxsData, *l2Tx)
1021 }
1022 for i := 0; i < numTxsL1Coord; i++ {
1023 bytesL1Coordinator :=
1024 aux.EncodedL1CoordinatorTx[i*common.RollupConstL1CoordinatorTotalBytes : (i+1)*common.RollupConstL1CoordinatorTotalBytes] //nolint:lll
1025 var signature []byte
1026 v := bytesL1Coordinator[0]
1027 s := bytesL1Coordinator[1:33]
1028 r := bytesL1Coordinator[33:65]
1029 signature = append(signature, r[:]...)
1030 signature = append(signature, s[:]...)
1031 signature = append(signature, v)
1032 l1Tx, err := common.L1CoordinatorTxFromBytes(bytesL1Coordinator, c.chainID, c.address)
1033 if err != nil {
1034 return nil, nil, tracerr.Wrap(err)
1035 }
1036 rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, *l1Tx)
1037 rollupForgeBatchArgs.L1CoordinatorTxsAuths =
1038 append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature)
1039 }
1040 lenFeeIdxCoordinatorBytes := int(nLevels / 8) //nolint:gomnd
1041 numFeeIdxCoordinator := len(aux.FeeIdxCoordinator) / lenFeeIdxCoordinatorBytes
1042 for i := 0; i < numFeeIdxCoordinator; i++ {
1043 var paddedFeeIdx [6]byte
1044 // TODO: This check is not necessary: the first case will always work. Test it
1045 // before removing the if.
1046 if lenFeeIdxCoordinatorBytes < common.IdxBytesLen {
1047 copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:],
1048 aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
1049 } else {
1050 copy(paddedFeeIdx[:],
1051 aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
1052 }
1053 feeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:])
1054 if err != nil {
1055 return nil, nil, tracerr.Wrap(err)
1056 }
1057 if feeIdxCoordinator != common.Idx(0) {
1058 rollupForgeBatchArgs.FeeIdxCoordinator =
1059 append(rollupForgeBatchArgs.FeeIdxCoordinator, feeIdxCoordinator)
1060 }
1061 }
1062 return &rollupForgeBatchArgs, &sender, nil
1063}