arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/eth/rollup.go
eth/rollup.goRaw
  1package eth
  2
  3import (
  4	"context"
  5	"fmt"
  6	"math/big"
  7	"strings"
  8
  9	"github.com/ethereum/go-ethereum"
 10	"github.com/ethereum/go-ethereum/accounts/abi"
 11	"github.com/ethereum/go-ethereum/accounts/abi/bind"
 12	ethCommon "github.com/ethereum/go-ethereum/common"
 13	"github.com/ethereum/go-ethereum/core/types"
 14	"github.com/ethereum/go-ethereum/crypto"
 15	"github.com/ethereum/go-ethereum/ethclient"
 16	"github.com/hermeznetwork/hermez-node/common"
 17	ERC777 "github.com/hermeznetwork/hermez-node/eth/contracts/erc777"
 18	Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez"
 19	"github.com/hermeznetwork/hermez-node/log"
 20	"github.com/iden3/go-iden3-crypto/babyjub"
 21	"golang.org/x/crypto/sha3"
 22)
 23
 24const (
 25	// RollupConstFeeIdxCoordinatorLen is the number of tokens the coordinator can use
 26	// to collect fees (determines the number of tokens that the
 27	// coordinator can collect fees from).  This value is determined by the
 28	// circuit.
 29	RollupConstFeeIdxCoordinatorLen = 64
 30	// RollupConstReservedIDx First 256 indexes reserved, first user index will be the 256
 31	RollupConstReservedIDx = 255
 32	// RollupConstExitIDx IDX 1 is reserved for exits
 33	RollupConstExitIDx = 1
 34	// RollupConstLimitLoadAmount Max load amount allowed (loadAmount: L1 --> L2)
 35	RollupConstLimitLoadAmount = (1 << 128)
 36	// RollupConstLimitL2TransferAmount Max amount allowed (amount L2 --> L2)
 37	RollupConstLimitL2TransferAmount = (1 << 192)
 38	// RollupConstLimitTokens Max number of tokens allowed to be registered inside the rollup
 39	RollupConstLimitTokens = (1 << 32)
 40	// RollupConstL1CoordinatorTotalBytes [4 bytes] token + [32 bytes] babyjub + [65 bytes] compressedSignature
 41	RollupConstL1CoordinatorTotalBytes = 101
 42	// RollupConstL1UserTotalBytes [20 bytes] fromEthAddr + [32 bytes] fromBjj-compressed + [6 bytes] fromIdx +
 43	// [2 bytes] loadAmountFloat16 + [2 bytes] amountFloat16 + [4 bytes] tokenId + [6 bytes] toIdx
 44	RollupConstL1UserTotalBytes = 72
 45	// RollupConstMaxL1UserTx Maximum L1-user transactions allowed to be queued in a batch
 46	RollupConstMaxL1UserTx = 128
 47	// RollupConstMaxL1Tx Maximum L1 transactions allowed to be queued in a batch
 48	RollupConstMaxL1Tx = 256
 49	// RollupConstInputSHAConstantBytes [6 bytes] lastIdx + [6 bytes] newLastIdx  + [32 bytes] stateRoot  + [32 bytes] newStRoot  + [32 bytes] newExitRoot +
 50	// [_MAX_L1_TX * _L1_USER_TOTALBYTES bytes] l1TxsData + totalL2TxsDataLength + feeIdxCoordinatorLength + [2 bytes] chainID =
 51	// 18542 bytes +  totalL2TxsDataLength + feeIdxCoordinatorLength
 52	RollupConstInputSHAConstantBytes = 18542
 53	// RollupConstNumBuckets Number of buckets
 54	RollupConstNumBuckets = 5
 55	// RollupConstMaxWithdrawalDelay max withdrawal delay in seconds
 56	RollupConstMaxWithdrawalDelay = 2 * 7 * 24 * 60 * 60
 57	// RollupConstExchangeMultiplier exchange multiplier
 58	RollupConstExchangeMultiplier = 1e14
 59	// LenVerifiers number of Rollup Smart Contract Verifiers
 60	LenVerifiers = 1
 61)
 62
 63var (
 64	// RollupConstEthAddressInternalOnly This ethereum address is used internally for rollup accounts that don't have ethereum address, only Babyjubjub
 65	// This non-ethereum accounts can be created by the coordinator and allow users to have a rollup
 66	// account without needing an ethereum address
 67	RollupConstEthAddressInternalOnly = ethCommon.HexToAddress("0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF")
 68	// RollupConstRfield Modulus zkSNARK
 69	RollupConstRfield, _ = new(big.Int).SetString(
 70		"21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
 71
 72	// RollupConstERC1820 ERC1820Registry address
 73	RollupConstERC1820 = ethCommon.HexToAddress("0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24")
 74
 75	// ERC777 tokens signatures
 76
 77	// RollupConstRecipientInterfaceHash ERC777 recipient interface hash
 78	RollupConstRecipientInterfaceHash = crypto.Keccak256([]byte("ERC777TokensRecipient"))
 79	// RollupConstPerformL1UserTxSignature the signature of the function that can be called thru an ERC777 `send`
 80	RollupConstPerformL1UserTxSignature = crypto.Keccak256([]byte("addL1Transaction(uint256,uint48,uint16,uint16,uint32,uint48)"))
 81	// RollupConstAddTokenSignature the signature of the function that can be called thru an ERC777 `send`
 82	RollupConstAddTokenSignature = crypto.Keccak256([]byte("addToken(address)"))
 83	// RollupConstSendSignature ERC777 Signature
 84	RollupConstSendSignature = crypto.Keccak256([]byte("send(address,uint256,bytes)"))
 85	// RollupConstERC777Granularity ERC777 Signature
 86	RollupConstERC777Granularity = crypto.Keccak256([]byte("granularity()"))
 87	// RollupConstWithdrawalDelayerDeposit  This constant are used to deposit tokens from ERC77 tokens into withdrawal delayer
 88	RollupConstWithdrawalDelayerDeposit = crypto.Keccak256([]byte("deposit(address,address,uint192)"))
 89
 90	// ERC20 signature
 91
 92	// RollupConstTransferSignature This constant is used in the _safeTransfer internal method in order to safe GAS.
 93	RollupConstTransferSignature = crypto.Keccak256([]byte("transfer(address,uint256)"))
 94	// RollupConstTransferFromSignature This constant is used in the _safeTransfer internal method in order to safe GAS.
 95	RollupConstTransferFromSignature = crypto.Keccak256([]byte("transferFrom(address,address,uint256)"))
 96	// RollupConstApproveSignature This constant is used in the _safeTransfer internal method in order to safe GAS.
 97	RollupConstApproveSignature = crypto.Keccak256([]byte("approve(address,uint256)"))
 98	// RollupConstERC20Signature ERC20 decimals signature
 99	RollupConstERC20Signature = crypto.Keccak256([]byte("decimals()"))
100)
101
102// RollupConstants are the constants of the Rollup Smart Contract
103/* type RollupConstants struct {
104	// Maxim Deposit allowed
105	MaxAmountDeposit *big.Int
106	MaxAmountL2      *big.Int
107	MaxTokens        int64
108	// maximum L1 transactions allowed to be queued for a batch
109	MaxL1Tx int
110	// maximum L1 user transactions allowed to be queued for a batch
111	MaxL1UserTx        int
112	Rfield             *big.Int
113	L1CoordinatorBytes int
114	L1UserBytes        int
115	L2Bytes            int
116	MaxTxVerifiers     []int
117	TokenHEZ           ethCommon.Address
118	// Only test
119	GovernanceAddress ethCommon.Address
120	// Only test
121	SafetyBot ethCommon.Address
122	// Only test
123	ConsensusContract ethCommon.Address
124	// Only test
125	WithdrawalContract ethCommon.Address
126	ReservedIDx        uint32
127	LastIDx            uint32
128	ExitIDx            uint32
129	NoLimitToken       int
130	NumBuckets         int
131	MaxWDelay          int64
132}*/
133
134// RollupPublicConstants are the constants of the Rollup Smart Contract
135type RollupPublicConstants struct {
136	AbsoluteMaxL1L2BatchTimeout int64
137	TokenHEZ                    ethCommon.Address
138	Verifiers                   []RollupVerifierStruct
139	HermezAuctionContract       ethCommon.Address
140	HermezGovernanceDAOAddress  ethCommon.Address
141	SafetyAddress               ethCommon.Address
142	WithdrawDelayerContract     ethCommon.Address
143}
144
145// RollupVariables are the variables of the Rollup Smart Contract
146type RollupVariables struct {
147	FeeAddToken           *big.Int
148	ForgeL1L2BatchTimeout int64
149	WithdrawalDelay       uint64
150}
151
152// QueueStruct is the queue of L1Txs for a batch
153//nolint:structcheck
154type QueueStruct struct {
155	L1TxQueue    []common.L1Tx
156	TotalL1TxFee *big.Int
157}
158
159// NewQueueStruct creates a new clear QueueStruct.
160func NewQueueStruct() *QueueStruct {
161	return &QueueStruct{
162		L1TxQueue:    make([]common.L1Tx, 0),
163		TotalL1TxFee: big.NewInt(0),
164	}
165}
166
167// RollupVerifierStruct is the information about verifiers of the Rollup Smart Contract
168type RollupVerifierStruct struct {
169	MaxTx   int64
170	NLevels int64
171}
172
173// RollupState represents the state of the Rollup in the Smart Contract
174//nolint:structcheck,unused
175type RollupState struct {
176	StateRoot              *big.Int
177	ExitRoots              []*big.Int
178	ExitNullifierMap       map[[256 / 8]byte]bool
179	TokenList              []ethCommon.Address
180	TokenMap               map[ethCommon.Address]bool
181	MapL1TxQueue           map[int64]*QueueStruct
182	LastL1L2Batch          int64
183	CurrentToForgeL1TxsNum int64
184	LastToForgeL1TxsNum    int64
185	CurrentIdx             int64
186}
187
188// RollupEventL1UserTx is an event of the Rollup Smart Contract
189type RollupEventL1UserTx struct {
190	ToForgeL1TxsNum int64 // QueueIndex       *big.Int
191	Position        int   // TransactionIndex *big.Int
192	L1Tx            common.L1Tx
193}
194
195// RollupEventL1UserTxAux is an event of the Rollup Smart Contract
196type RollupEventL1UserTxAux struct {
197	ToForgeL1TxsNum uint64 // QueueIndex       *big.Int
198	Position        uint8  // TransactionIndex *big.Int
199	L1Tx            []byte
200}
201
202// RollupEventAddToken is an event of the Rollup Smart Contract
203type RollupEventAddToken struct {
204	Address ethCommon.Address
205	TokenID uint32
206}
207
208// RollupEventForgeBatch is an event of the Rollup Smart Contract
209type RollupEventForgeBatch struct {
210	BatchNum  int64
211	EthTxHash ethCommon.Hash
212}
213
214// RollupEventUpdateForgeL1L2BatchTimeout is an event of the Rollup Smart Contract
215type RollupEventUpdateForgeL1L2BatchTimeout struct {
216	ForgeL1L2BatchTimeout uint8
217}
218
219// RollupEventUpdateFeeAddToken is an event of the Rollup Smart Contract
220type RollupEventUpdateFeeAddToken struct {
221	FeeAddToken *big.Int
222}
223
224// RollupEventWithdrawEvent is an event of the Rollup Smart Contract
225type RollupEventWithdrawEvent struct {
226	Idx             uint64
227	NumExitRoot     uint64
228	InstantWithdraw bool
229}
230
231// RollupEvents is the list of events in a block of the Rollup Smart Contract
232type RollupEvents struct { //nolint:structcheck
233	L1UserTx                    []RollupEventL1UserTx
234	AddToken                    []RollupEventAddToken
235	ForgeBatch                  []RollupEventForgeBatch
236	UpdateForgeL1L2BatchTimeout []RollupEventUpdateForgeL1L2BatchTimeout
237	UpdateFeeAddToken           []RollupEventUpdateFeeAddToken
238	WithdrawEvent               []RollupEventWithdrawEvent
239}
240
241// NewRollupEvents creates an empty RollupEvents with the slices initialized.
242func NewRollupEvents() RollupEvents {
243	return RollupEvents{
244		L1UserTx:                    make([]RollupEventL1UserTx, 0),
245		AddToken:                    make([]RollupEventAddToken, 0),
246		ForgeBatch:                  make([]RollupEventForgeBatch, 0),
247		UpdateForgeL1L2BatchTimeout: make([]RollupEventUpdateForgeL1L2BatchTimeout, 0),
248		UpdateFeeAddToken:           make([]RollupEventUpdateFeeAddToken, 0),
249		WithdrawEvent:               make([]RollupEventWithdrawEvent, 0),
250	}
251}
252
253// RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
254//nolint:structcheck,unused
255type RollupForgeBatchArgs struct {
256	NewLastIdx            int64
257	NewStRoot             *big.Int
258	NewExitRoot           *big.Int
259	L1CoordinatorTxs      []*common.L1Tx
260	L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx
261	L2TxsData             []*common.L2Tx
262	FeeIdxCoordinator     []common.Idx
263	// Circuit selector
264	VerifierIdx uint8
265	L1Batch     bool
266	ProofA      [2]*big.Int
267	ProofB      [2][2]*big.Int
268	ProofC      [2]*big.Int
269}
270
271// RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract
272//nolint:structcheck,unused
273type RollupForgeBatchArgsAux struct {
274	NewLastIdx             *big.Int
275	NewStRoot              *big.Int
276	NewExitRoot            *big.Int
277	EncodedL1CoordinatorTx []byte
278	L2TxsData              []byte
279	FeeIdxCoordinator      []byte
280	// Circuit selector
281	VerifierIdx uint8
282	L1Batch     bool
283	ProofA      [2]*big.Int
284	ProofB      [2][2]*big.Int
285	ProofC      [2]*big.Int
286}
287
288// RollupInterface is the inteface to to Rollup Smart Contract
289type RollupInterface interface {
290	//
291	// Smart Contract Methods
292	//
293
294	// Public Functions
295
296	RollupForgeBatch(*RollupForgeBatchArgs) (*types.Transaction, error)
297	RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error)
298	RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey,
299		numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error)
300	RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error)
301	RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error)
302	RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey,
303		loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error)
304	RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16,
305		tokenID int64, toIdx int64) (*types.Transaction, error)
306	RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error)
307	RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte,
308		babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error)
309	RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16,
310		tokenID int64) (*types.Transaction, error)
311
312	RollupGetCurrentTokens() (*big.Int, error)
313	// RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error)
314	// RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error)
315	// RollupGetQueue(queue int64) ([]byte, error)
316
317	// Governance Public Functions
318	RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (*types.Transaction, error)
319	RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error)
320
321	//
322	// Smart Contract Status
323	//
324
325	RollupConstants() (*RollupPublicConstants, error)
326	RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error)
327	RollupForgeBatchArgs(ethCommon.Hash) (*RollupForgeBatchArgs, error)
328}
329
330//
331// Implementation
332//
333
334// RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum.
335type RollupClient struct {
336	client       *EthereumClient
337	address      ethCommon.Address
338	tokenAddress ethCommon.Address
339	gasLimit     uint64
340	contractAbi  abi.ABI
341}
342
343// NewRollupClient creates a new RollupClient
344func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenAddress ethCommon.Address) (*RollupClient, error) {
345	contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI)))
346	if err != nil {
347		return nil, err
348	}
349	return &RollupClient{
350		client:       client,
351		address:      address,
352		tokenAddress: tokenAddress,
353		gasLimit:     1000000, //nolint:gomnd
354		contractAbi:  contractAbi,
355	}, nil
356}
357
358// RollupForgeBatch is the interface to call the smart contract function
359func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (*types.Transaction, error) {
360	var tx *types.Transaction
361	var err error
362	if tx, err = c.client.CallAuth(
363		c.gasLimit,
364		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
365			hermez, err := Hermez.NewHermez(c.address, ec)
366			if err != nil {
367				return nil, err
368			}
369			rollupConst, err := c.RollupConstants()
370			if err != nil {
371				return nil, err
372			}
373			nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels
374			lenBytes := nLevels / 8
375			newLastIdx := big.NewInt(int64(args.NewLastIdx))
376			var l1CoordinatorBytes []byte
377			for i := 0; i < len(args.L1CoordinatorTxs); i++ {
378				l1 := args.L1CoordinatorTxs[i]
379				bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i])
380				if err != nil {
381					return nil, err
382				}
383				l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...)
384			}
385			var l2DataBytes []byte
386			for i := 0; i < len(args.L2TxsData); i++ {
387				l2 := args.L2TxsData[i]
388				bytesl2, err := l2.Bytes(int(nLevels))
389				if err != nil {
390					return nil, err
391				}
392				l2DataBytes = append(l2DataBytes, bytesl2[:]...)
393			}
394			var feeIdxCoordinator []byte
395			for i := 0; i < len(args.FeeIdxCoordinator); i++ {
396				feeIdx := args.FeeIdxCoordinator[i]
397				bytesFeeIdx, err := feeIdx.Bytes()
398				if err != nil {
399					return nil, err
400				}
401				feeIdxCoordinator = append(feeIdxCoordinator, bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...)
402			}
403			return hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot, l1CoordinatorBytes, l2DataBytes, feeIdxCoordinator, args.VerifierIdx, args.L1Batch, args.ProofA, args.ProofB, args.ProofC)
404		},
405	); err != nil {
406		return nil, fmt.Errorf("Failed forge batch: %w", err)
407	}
408	return tx, nil
409}
410
411// RollupAddToken is the interface to call the smart contract function
412func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error) {
413	var tx *types.Transaction
414	var err error
415	if tx, err = c.client.CallAuth(
416		c.gasLimit,
417		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
418			tokens, err := ERC777.NewERC777(c.tokenAddress, ec)
419			if err != nil {
420				return nil, err
421			}
422			addTokenFnSignature := []byte("addToken(address)")
423			hash := sha3.NewLegacyKeccak256()
424			_, err = hash.Write(addTokenFnSignature)
425			if err != nil {
426				return nil, err
427			}
428			methodID := hash.Sum(nil)[:4]
429			var data []byte
430			data = append(data, methodID...)
431			paddedAddress := ethCommon.LeftPadBytes(tokenAddress.Bytes(), 32)
432			data = append(data, paddedAddress[:]...)
433			return tokens.Send(auth, c.address, feeAddToken, data)
434		},
435	); err != nil {
436		return nil, fmt.Errorf("Failed add Token %w", err)
437	}
438	return tx, nil
439}
440
441// RollupWithdrawSNARK is the interface to call the smart contract function
442// func (c *RollupClient) RollupWithdrawSNARK() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
443// 	return nil, errTODO
444// }
445
446// RollupWithdraw is the interface to call the smart contract function
447func (c *RollupClient) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) {
448	log.Error("TODO")
449	return nil, errTODO
450}
451
452// RollupForceExit is the interface to call the smart contract function
453func (c *RollupClient) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error) {
454	log.Error("TODO")
455	return nil, errTODO
456}
457
458// RollupForceTransfer is the interface to call the smart contract function
459func (c *RollupClient) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
460	log.Error("TODO")
461	return nil, errTODO
462}
463
464// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
465func (c *RollupClient) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
466	log.Error("TODO")
467	return nil, errTODO
468}
469
470// RollupDepositTransfer is the interface to call the smart contract function
471func (c *RollupClient) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
472	log.Error("TODO")
473	return nil, errTODO
474}
475
476// RollupDeposit is the interface to call the smart contract function
477func (c *RollupClient) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
478	log.Error("TODO")
479	return nil, errTODO
480}
481
482// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
483func (c *RollupClient) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error) {
484	log.Error("TODO")
485	return nil, errTODO
486}
487
488// RollupCreateAccountDeposit is the interface to call the smart contract function
489func (c *RollupClient) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
490	log.Error("TODO")
491	return nil, errTODO
492}
493
494// RollupGetTokenAddress is the interface to call the smart contract function
495/* func (c *RollupClient) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
496	return nil, errTODO
497} */
498
499// RollupGetCurrentTokens is the interface to call the smart contract function
500func (c *RollupClient) RollupGetCurrentTokens() (*big.Int, error) {
501	log.Error("TODO")
502	return nil, errTODO
503}
504
505// RollupGetL1TxFromQueue is the interface to call the smart contract function
506/* func (c *RollupClient) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
507	return nil, errTODO
508} */
509
510// RollupGetQueue is the interface to call the smart contract function
511/* func (c *RollupClient) RollupGetQueue(queue int64) ([]byte, error) {
512	return nil, errTODO
513}*/
514
515// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
516func (c *RollupClient) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (*types.Transaction, error) {
517	log.Error("TODO")
518	return nil, errTODO
519}
520
521// RollupUpdateFeeAddToken is the interface to call the smart contract function
522func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error) {
523	log.Error("TODO")
524	return nil, errTODO
525}
526
527// RollupConstants returns the Constants of the Rollup Smart Contract
528func (c *RollupClient) RollupConstants() (*RollupPublicConstants, error) {
529	rollupConstants := new(RollupPublicConstants)
530	if err := c.client.Call(func(ec *ethclient.Client) error {
531		hermez, err := Hermez.NewHermez(c.address, ec)
532		if err != nil {
533			return err
534		}
535		absoluteMaxL1L2BatchTimeout, err := hermez.ABSOLUTEMAXL1L2BATCHTIMEOUT(nil)
536		if err != nil {
537			return err
538		}
539		rollupConstants.AbsoluteMaxL1L2BatchTimeout = int64(absoluteMaxL1L2BatchTimeout)
540		rollupConstants.TokenHEZ, err = hermez.TokenHEZ(nil)
541		if err != nil {
542			return err
543		}
544		for i := int64(0); i < int64(LenVerifiers); i++ {
545			var newRollupVerifier RollupVerifierStruct
546			rollupVerifier, err := hermez.RollupVerifiers(nil, big.NewInt(i))
547			if err != nil {
548				return err
549			}
550			newRollupVerifier.MaxTx = rollupVerifier.MaxTx.Int64()
551			newRollupVerifier.NLevels = rollupVerifier.NLevels.Int64()
552			rollupConstants.Verifiers = append(rollupConstants.Verifiers, newRollupVerifier)
553		}
554		rollupConstants.HermezAuctionContract, err = hermez.HermezAuctionContract(nil)
555		if err != nil {
556			return err
557		}
558		rollupConstants.HermezGovernanceDAOAddress, err = hermez.HermezGovernanceDAOAddress(nil)
559		if err != nil {
560			return err
561		}
562		rollupConstants.SafetyAddress, err = hermez.SafetyAddress(nil)
563		if err != nil {
564			return err
565		}
566		rollupConstants.WithdrawDelayerContract, err = hermez.WithdrawDelayerContract(nil)
567		return err
568	}); err != nil {
569		return nil, err
570	}
571	return rollupConstants, nil
572}
573
574var (
575	logHermezL1UserTxEvent               = crypto.Keccak256Hash([]byte("L1UserTxEvent(uint64,uint8,bytes)"))
576	logHermezAddToken                    = crypto.Keccak256Hash([]byte("AddToken(address,uint32)"))
577	logHermezForgeBatch                  = crypto.Keccak256Hash([]byte("ForgeBatch(uint64)"))
578	logHermezUpdateForgeL1L2BatchTimeout = crypto.Keccak256Hash([]byte("UpdateForgeL1L2BatchTimeout(uint8)"))
579	logHermezUpdateFeeAddToken           = crypto.Keccak256Hash([]byte("UpdateFeeAddToken(uint256)"))
580	logHermezWithdrawEvent               = crypto.Keccak256Hash([]byte("WithdrawEvent(uint48,uint48,bool)"))
581)
582
583// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
584func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error) {
585	var rollupEvents RollupEvents
586	var blockHash ethCommon.Hash
587
588	query := ethereum.FilterQuery{
589		FromBlock: big.NewInt(blockNum),
590		ToBlock:   big.NewInt(blockNum),
591		Addresses: []ethCommon.Address{
592			c.address,
593		},
594		BlockHash: nil,
595		Topics:    [][]ethCommon.Hash{},
596	}
597	logs, err := c.client.client.FilterLogs(context.Background(), query)
598	if err != nil {
599		return nil, nil, err
600	}
601	if len(logs) > 0 {
602		blockHash = logs[0].BlockHash
603	}
604	for _, vLog := range logs {
605		if vLog.BlockHash != blockHash {
606			return nil, nil, ErrBlockHashMismatchEvent
607		}
608		switch vLog.Topics[0] {
609		case logHermezL1UserTxEvent:
610			var L1UserTxAux RollupEventL1UserTxAux
611			var L1UserTx RollupEventL1UserTx
612			err := c.contractAbi.Unpack(&L1UserTxAux, "L1UserTxEvent", vLog.Data)
613			if err != nil {
614				return nil, nil, err
615			}
616			L1Tx, err := common.L1TxFromBytes(L1UserTxAux.L1Tx)
617			if err != nil {
618				return nil, nil, err
619			}
620			L1UserTx.ToForgeL1TxsNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
621			L1UserTx.Position = int(new(big.Int).SetBytes(vLog.Topics[2][:]).Int64())
622			L1UserTx.L1Tx = *L1Tx
623			rollupEvents.L1UserTx = append(rollupEvents.L1UserTx, L1UserTx)
624		case logHermezAddToken:
625			var addToken RollupEventAddToken
626			err := c.contractAbi.Unpack(&addToken, "AddToken", vLog.Data)
627			if err != nil {
628				return nil, nil, err
629			}
630			addToken.Address = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
631			rollupEvents.AddToken = append(rollupEvents.AddToken, addToken)
632		case logHermezForgeBatch:
633			var forgeBatch RollupEventForgeBatch
634			forgeBatch.BatchNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
635			forgeBatch.EthTxHash = vLog.TxHash
636			rollupEvents.ForgeBatch = append(rollupEvents.ForgeBatch, forgeBatch)
637		case logHermezUpdateForgeL1L2BatchTimeout:
638			var updateForgeL1L2BatchTimeout RollupEventUpdateForgeL1L2BatchTimeout
639			err := c.contractAbi.Unpack(&updateForgeL1L2BatchTimeout, "UpdateForgeL1L2BatchTimeout", vLog.Data)
640			if err != nil {
641				return nil, nil, err
642			}
643			rollupEvents.UpdateForgeL1L2BatchTimeout = append(rollupEvents.UpdateForgeL1L2BatchTimeout, updateForgeL1L2BatchTimeout)
644		case logHermezUpdateFeeAddToken:
645			var updateFeeAddToken RollupEventUpdateFeeAddToken
646			err := c.contractAbi.Unpack(&updateFeeAddToken, "UpdateFeeAddToken", vLog.Data)
647			if err != nil {
648				return nil, nil, err
649			}
650			rollupEvents.UpdateFeeAddToken = append(rollupEvents.UpdateFeeAddToken, updateFeeAddToken)
651		case logHermezWithdrawEvent:
652			var withdraw RollupEventWithdrawEvent
653			err := c.contractAbi.Unpack(&withdraw, "WithdrawEvent", vLog.Data)
654			if err != nil {
655				return nil, nil, err
656			}
657			withdraw.Idx = new(big.Int).SetBytes(vLog.Topics[1][:]).Uint64()
658			withdraw.NumExitRoot = new(big.Int).SetBytes(vLog.Topics[2][:]).Uint64()
659			rollupEvents.WithdrawEvent = append(rollupEvents.WithdrawEvent, withdraw)
660		}
661	}
662	return &rollupEvents, &blockHash, nil
663}
664
665// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
666func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupForgeBatchArgs, error) {
667	tx, _, err := c.client.client.TransactionByHash(context.Background(), ethTxHash)
668	if err != nil {
669		return nil, err
670	}
671	txData := tx.Data()
672	method, err := c.contractAbi.MethodById(txData[:4])
673	if err != nil {
674		return nil, err
675	}
676	var aux RollupForgeBatchArgsAux
677	if err := method.Inputs.Unpack(&aux, txData[4:]); err != nil {
678		return nil, err
679	}
680	var rollupForgeBatchArgs RollupForgeBatchArgs
681	rollupForgeBatchArgs.L1Batch = aux.L1Batch
682	rollupForgeBatchArgs.NewExitRoot = aux.NewExitRoot
683	rollupForgeBatchArgs.NewLastIdx = aux.NewLastIdx.Int64()
684	rollupForgeBatchArgs.NewStRoot = aux.NewStRoot
685	rollupForgeBatchArgs.ProofA = aux.ProofA
686	rollupForgeBatchArgs.ProofB = aux.ProofB
687	rollupForgeBatchArgs.ProofC = aux.ProofC
688	rollupForgeBatchArgs.VerifierIdx = aux.VerifierIdx
689	numTxsL1 := len(aux.EncodedL1CoordinatorTx) / common.L1CoordinatorTxBytesLen
690	for i := 0; i < numTxsL1; i++ {
691		bytesL1Coordinator := aux.EncodedL1CoordinatorTx[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen]
692		var signature []byte
693		v := bytesL1Coordinator[0]
694		s := bytesL1Coordinator[1:33]
695		r := bytesL1Coordinator[33:65]
696		signature = append(signature, r[:]...)
697		signature = append(signature, s[:]...)
698		signature = append(signature, v)
699		l1Tx, err := common.L1TxFromCoordinatorBytes(bytesL1Coordinator)
700		if err != nil {
701			return nil, err
702		}
703		rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, l1Tx)
704		rollupForgeBatchArgs.L1CoordinatorTxsAuths = append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature)
705	}
706	rollupConsts, err := c.RollupConstants()
707	if err != nil {
708		return nil, err
709	}
710	nLevels := rollupConsts.Verifiers[rollupForgeBatchArgs.VerifierIdx].NLevels
711	lenL2TxsBytes := int((nLevels/8)*2 + 2 + 1)
712	numTxsL2 := len(aux.L2TxsData) / lenL2TxsBytes
713	for i := 0; i < numTxsL2; i++ {
714		l2Tx, err := common.L2TxFromBytes(aux.L2TxsData[i*lenL2TxsBytes:(i+1)*lenL2TxsBytes], int(nLevels))
715		if err != nil {
716			return nil, err
717		}
718		rollupForgeBatchArgs.L2TxsData = append(rollupForgeBatchArgs.L2TxsData, l2Tx)
719	}
720	lenFeeIdxCoordinatorBytes := int(nLevels / 8) //nolint:gomnd
721	numFeeIdxCoordinator := len(aux.FeeIdxCoordinator) / lenFeeIdxCoordinatorBytes
722	for i := 0; i < numFeeIdxCoordinator; i++ {
723		var paddedFeeIdx [6]byte
724		// TODO: This check is not necessary: the first case will always work.  Test it before removing the if.
725		if lenFeeIdxCoordinatorBytes < common.IdxBytesLen {
726			copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
727		} else {
728			copy(paddedFeeIdx[:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
729		}
730		FeeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:])
731		if err != nil {
732			return nil, err
733		}
734		rollupForgeBatchArgs.FeeIdxCoordinator = append(rollupForgeBatchArgs.FeeIdxCoordinator, FeeIdxCoordinator)
735	}
736	return &rollupForgeBatchArgs, nil
737}