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
153type QueueStruct struct {
154	L1TxQueue    []common.L1Tx
155	TotalL1TxFee *big.Int
156}
157
158// NewQueueStruct creates a new clear QueueStruct.
159func NewQueueStruct() *QueueStruct {
160	return &QueueStruct{
161		L1TxQueue:    make([]common.L1Tx, 0),
162		TotalL1TxFee: big.NewInt(0),
163	}
164}
165
166// RollupVerifierStruct is the information about verifiers of the Rollup Smart Contract
167type RollupVerifierStruct struct {
168	MaxTx   int64
169	NLevels int64
170}
171
172// RollupState represents the state of the Rollup in the Smart Contract
173type RollupState struct {
174	StateRoot              *big.Int
175	ExitRoots              []*big.Int
176	ExitNullifierMap       map[[256 / 8]byte]bool
177	TokenList              []ethCommon.Address
178	TokenMap               map[ethCommon.Address]bool
179	MapL1TxQueue           map[int64]*QueueStruct
180	LastL1L2Batch          int64
181	CurrentToForgeL1TxsNum int64
182	LastToForgeL1TxsNum    int64
183	CurrentIdx             int64
184}
185
186// RollupEventL1UserTx is an event of the Rollup Smart Contract
187type RollupEventL1UserTx struct {
188	ToForgeL1TxsNum int64 // QueueIndex       *big.Int
189	Position        int   // TransactionIndex *big.Int
190	L1Tx            common.L1Tx
191}
192
193// RollupEventL1UserTxAux is an event of the Rollup Smart Contract
194type RollupEventL1UserTxAux struct {
195	ToForgeL1TxsNum uint64 // QueueIndex       *big.Int
196	Position        uint8  // TransactionIndex *big.Int
197	L1Tx            []byte
198}
199
200// RollupEventAddToken is an event of the Rollup Smart Contract
201type RollupEventAddToken struct {
202	Address ethCommon.Address
203	TokenID uint32
204}
205
206// RollupEventForgeBatch is an event of the Rollup Smart Contract
207type RollupEventForgeBatch struct {
208	BatchNum  int64
209	EthTxHash ethCommon.Hash
210}
211
212// RollupEventUpdateForgeL1L2BatchTimeout is an event of the Rollup Smart Contract
213type RollupEventUpdateForgeL1L2BatchTimeout struct {
214	ForgeL1L2BatchTimeout uint8
215}
216
217// RollupEventUpdateFeeAddToken is an event of the Rollup Smart Contract
218type RollupEventUpdateFeeAddToken struct {
219	FeeAddToken *big.Int
220}
221
222// RollupEventWithdrawEvent is an event of the Rollup Smart Contract
223type RollupEventWithdrawEvent struct {
224	Idx             uint64
225	NumExitRoot     uint64
226	InstantWithdraw bool
227}
228
229// RollupEvents is the list of events in a block of the Rollup Smart Contract
230type RollupEvents struct {
231	L1UserTx                    []RollupEventL1UserTx
232	AddToken                    []RollupEventAddToken
233	ForgeBatch                  []RollupEventForgeBatch
234	UpdateForgeL1L2BatchTimeout []RollupEventUpdateForgeL1L2BatchTimeout
235	UpdateFeeAddToken           []RollupEventUpdateFeeAddToken
236	WithdrawEvent               []RollupEventWithdrawEvent
237}
238
239// NewRollupEvents creates an empty RollupEvents with the slices initialized.
240func NewRollupEvents() RollupEvents {
241	return RollupEvents{
242		L1UserTx:                    make([]RollupEventL1UserTx, 0),
243		AddToken:                    make([]RollupEventAddToken, 0),
244		ForgeBatch:                  make([]RollupEventForgeBatch, 0),
245		UpdateForgeL1L2BatchTimeout: make([]RollupEventUpdateForgeL1L2BatchTimeout, 0),
246		UpdateFeeAddToken:           make([]RollupEventUpdateFeeAddToken, 0),
247		WithdrawEvent:               make([]RollupEventWithdrawEvent, 0),
248	}
249}
250
251// RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
252type RollupForgeBatchArgs struct {
253	NewLastIdx            int64
254	NewStRoot             *big.Int
255	NewExitRoot           *big.Int
256	L1CoordinatorTxs      []*common.L1Tx
257	L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx
258	L2TxsData             []*common.L2Tx
259	FeeIdxCoordinator     []common.Idx
260	// Circuit selector
261	VerifierIdx uint8
262	L1Batch     bool
263	ProofA      [2]*big.Int
264	ProofB      [2][2]*big.Int
265	ProofC      [2]*big.Int
266}
267
268// RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract
269type RollupForgeBatchArgsAux struct {
270	NewLastIdx             *big.Int
271	NewStRoot              *big.Int
272	NewExitRoot            *big.Int
273	EncodedL1CoordinatorTx []byte
274	L2TxsData              []byte
275	FeeIdxCoordinator      []byte
276	// Circuit selector
277	VerifierIdx uint8
278	L1Batch     bool
279	ProofA      [2]*big.Int
280	ProofB      [2][2]*big.Int
281	ProofC      [2]*big.Int
282}
283
284// RollupInterface is the inteface to to Rollup Smart Contract
285type RollupInterface interface {
286	//
287	// Smart Contract Methods
288	//
289
290	// Public Functions
291
292	RollupForgeBatch(*RollupForgeBatchArgs) (*types.Transaction, error)
293	RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error)
294	RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey,
295		numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error)
296	RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error)
297	RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error)
298	RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey,
299		loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error)
300	RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16,
301		tokenID int64, toIdx int64) (*types.Transaction, error)
302	RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error)
303	RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte,
304		babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error)
305	RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16,
306		tokenID int64) (*types.Transaction, error)
307
308	RollupGetCurrentTokens() (*big.Int, error)
309	// RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error)
310	// RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error)
311	// RollupGetQueue(queue int64) ([]byte, error)
312
313	// Governance Public Functions
314	RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (*types.Transaction, error)
315	RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error)
316
317	//
318	// Smart Contract Status
319	//
320
321	RollupConstants() (*RollupPublicConstants, error)
322	RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error)
323	RollupForgeBatchArgs(ethCommon.Hash) (*RollupForgeBatchArgs, error)
324}
325
326//
327// Implementation
328//
329
330// RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum.
331type RollupClient struct {
332	client          *EthereumClient
333	address         ethCommon.Address
334	tokenHEZAddress ethCommon.Address
335	gasLimit        uint64
336	contractAbi     abi.ABI
337}
338
339// NewRollupClient creates a new RollupClient
340func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenHEZAddress ethCommon.Address) (*RollupClient, error) {
341	contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI)))
342	if err != nil {
343		return nil, err
344	}
345	return &RollupClient{
346		client:          client,
347		address:         address,
348		tokenHEZAddress: tokenHEZAddress,
349		gasLimit:        1000000, //nolint:gomnd
350		contractAbi:     contractAbi,
351	}, nil
352}
353
354// RollupForgeBatch is the interface to call the smart contract function
355func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (*types.Transaction, error) {
356	var tx *types.Transaction
357	var err error
358	if tx, err = c.client.CallAuth(
359		c.gasLimit,
360		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
361			hermez, err := Hermez.NewHermez(c.address, ec)
362			if err != nil {
363				return nil, err
364			}
365			rollupConst, err := c.RollupConstants()
366			if err != nil {
367				return nil, err
368			}
369			nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels
370			lenBytes := nLevels / 8 //nolint:gomnd
371			newLastIdx := big.NewInt(int64(args.NewLastIdx))
372			var l1CoordinatorBytes []byte
373			for i := 0; i < len(args.L1CoordinatorTxs); i++ {
374				l1 := args.L1CoordinatorTxs[i]
375				bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i])
376				if err != nil {
377					return nil, err
378				}
379				l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...)
380			}
381			var l2DataBytes []byte
382			for i := 0; i < len(args.L2TxsData); i++ {
383				l2 := args.L2TxsData[i]
384				bytesl2, err := l2.Bytes(int(nLevels))
385				if err != nil {
386					return nil, err
387				}
388				l2DataBytes = append(l2DataBytes, bytesl2[:]...)
389			}
390			var feeIdxCoordinator []byte
391			for i := 0; i < len(args.FeeIdxCoordinator); i++ {
392				feeIdx := args.FeeIdxCoordinator[i]
393				bytesFeeIdx, err := feeIdx.Bytes()
394				if err != nil {
395					return nil, err
396				}
397				feeIdxCoordinator = append(feeIdxCoordinator, bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...)
398			}
399			return hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot, l1CoordinatorBytes, l2DataBytes, feeIdxCoordinator, args.VerifierIdx, args.L1Batch, args.ProofA, args.ProofB, args.ProofC)
400		},
401	); err != nil {
402		return nil, fmt.Errorf("Failed forge batch: %w", err)
403	}
404	return tx, nil
405}
406
407// RollupAddToken is the interface to call the smart contract function.
408// `feeAddToken` is the amount of HEZ tokens that will be paid to add the
409// token.  `feeAddToken` must match the public value of the smart contract.
410func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error) {
411	var tx *types.Transaction
412	var err error
413	if tx, err = c.client.CallAuth(
414		c.gasLimit,
415		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
416			tokens, err := ERC777.NewERC777(c.tokenHEZAddress, ec)
417			if err != nil {
418				return nil, err
419			}
420			addTokenFnSignature := []byte("addToken(address)")
421			hash := sha3.NewLegacyKeccak256()
422			_, err = hash.Write(addTokenFnSignature)
423			if err != nil {
424				return nil, err
425			}
426			methodID := hash.Sum(nil)[:4]
427			var data []byte
428			data = append(data, methodID...)
429			paddedAddress := ethCommon.LeftPadBytes(tokenAddress.Bytes(), 32)
430			data = append(data, paddedAddress[:]...)
431			return tokens.Send(auth, c.address, feeAddToken, data)
432		},
433	); err != nil {
434		return nil, fmt.Errorf("Failed add Token %w", err)
435	}
436	return tx, nil
437}
438
439// RollupWithdrawSNARK is the interface to call the smart contract function
440// func (c *RollupClient) RollupWithdrawSNARK() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
441// 	return nil, errTODO
442// }
443
444// RollupWithdraw is the interface to call the smart contract function
445func (c *RollupClient) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) {
446	log.Error("TODO")
447	return nil, errTODO
448}
449
450// RollupForceExit is the interface to call the smart contract function
451func (c *RollupClient) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error) {
452	log.Error("TODO")
453	return nil, errTODO
454}
455
456// RollupForceTransfer is the interface to call the smart contract function
457func (c *RollupClient) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
458	log.Error("TODO")
459	return nil, errTODO
460}
461
462// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
463func (c *RollupClient) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
464	log.Error("TODO")
465	return nil, errTODO
466}
467
468// RollupDepositTransfer is the interface to call the smart contract function
469func (c *RollupClient) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
470	log.Error("TODO")
471	return nil, errTODO
472}
473
474// RollupDeposit is the interface to call the smart contract function
475func (c *RollupClient) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
476	log.Error("TODO")
477	return nil, errTODO
478}
479
480// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
481func (c *RollupClient) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error) {
482	log.Error("TODO")
483	return nil, errTODO
484}
485
486// RollupCreateAccountDeposit is the interface to call the smart contract function
487func (c *RollupClient) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
488	log.Error("TODO")
489	return nil, errTODO
490}
491
492// RollupGetTokenAddress is the interface to call the smart contract function
493/* func (c *RollupClient) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
494	return nil, errTODO
495} */
496
497// RollupGetCurrentTokens is the interface to call the smart contract function
498func (c *RollupClient) RollupGetCurrentTokens() (*big.Int, error) {
499	log.Error("TODO")
500	return nil, errTODO
501}
502
503// RollupGetL1TxFromQueue is the interface to call the smart contract function
504/* func (c *RollupClient) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
505	return nil, errTODO
506} */
507
508// RollupGetQueue is the interface to call the smart contract function
509/* func (c *RollupClient) RollupGetQueue(queue int64) ([]byte, error) {
510	return nil, errTODO
511}*/
512
513// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
514func (c *RollupClient) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (*types.Transaction, error) {
515	log.Error("TODO")
516	return nil, errTODO
517}
518
519// RollupUpdateFeeAddToken is the interface to call the smart contract function
520func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error) {
521	log.Error("TODO")
522	return nil, errTODO
523}
524
525// RollupConstants returns the Constants of the Rollup Smart Contract
526func (c *RollupClient) RollupConstants() (*RollupPublicConstants, error) {
527	rollupConstants := new(RollupPublicConstants)
528	if err := c.client.Call(func(ec *ethclient.Client) error {
529		hermez, err := Hermez.NewHermez(c.address, ec)
530		if err != nil {
531			return err
532		}
533		absoluteMaxL1L2BatchTimeout, err := hermez.ABSOLUTEMAXL1L2BATCHTIMEOUT(nil)
534		if err != nil {
535			return err
536		}
537		rollupConstants.AbsoluteMaxL1L2BatchTimeout = int64(absoluteMaxL1L2BatchTimeout)
538		rollupConstants.TokenHEZ, err = hermez.TokenHEZ(nil)
539		if err != nil {
540			return err
541		}
542		for i := int64(0); i < int64(LenVerifiers); i++ {
543			var newRollupVerifier RollupVerifierStruct
544			rollupVerifier, err := hermez.RollupVerifiers(nil, big.NewInt(i))
545			if err != nil {
546				return err
547			}
548			newRollupVerifier.MaxTx = rollupVerifier.MaxTx.Int64()
549			newRollupVerifier.NLevels = rollupVerifier.NLevels.Int64()
550			rollupConstants.Verifiers = append(rollupConstants.Verifiers, newRollupVerifier)
551		}
552		rollupConstants.HermezAuctionContract, err = hermez.HermezAuctionContract(nil)
553		if err != nil {
554			return err
555		}
556		rollupConstants.HermezGovernanceDAOAddress, err = hermez.HermezGovernanceDAOAddress(nil)
557		if err != nil {
558			return err
559		}
560		rollupConstants.SafetyAddress, err = hermez.SafetyAddress(nil)
561		if err != nil {
562			return err
563		}
564		rollupConstants.WithdrawDelayerContract, err = hermez.WithdrawDelayerContract(nil)
565		return err
566	}); err != nil {
567		return nil, err
568	}
569	return rollupConstants, nil
570}
571
572var (
573	logHermezL1UserTxEvent               = crypto.Keccak256Hash([]byte("L1UserTxEvent(uint64,uint8,bytes)"))
574	logHermezAddToken                    = crypto.Keccak256Hash([]byte("AddToken(address,uint32)"))
575	logHermezForgeBatch                  = crypto.Keccak256Hash([]byte("ForgeBatch(uint64)"))
576	logHermezUpdateForgeL1L2BatchTimeout = crypto.Keccak256Hash([]byte("UpdateForgeL1L2BatchTimeout(uint8)"))
577	logHermezUpdateFeeAddToken           = crypto.Keccak256Hash([]byte("UpdateFeeAddToken(uint256)"))
578	logHermezWithdrawEvent               = crypto.Keccak256Hash([]byte("WithdrawEvent(uint48,uint48,bool)"))
579)
580
581// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
582func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error) {
583	var rollupEvents RollupEvents
584	var blockHash ethCommon.Hash
585
586	query := ethereum.FilterQuery{
587		FromBlock: big.NewInt(blockNum),
588		ToBlock:   big.NewInt(blockNum),
589		Addresses: []ethCommon.Address{
590			c.address,
591		},
592		BlockHash: nil,
593		Topics:    [][]ethCommon.Hash{},
594	}
595	logs, err := c.client.client.FilterLogs(context.Background(), query)
596	if err != nil {
597		return nil, nil, err
598	}
599	if len(logs) > 0 {
600		blockHash = logs[0].BlockHash
601	}
602	for _, vLog := range logs {
603		if vLog.BlockHash != blockHash {
604			return nil, nil, ErrBlockHashMismatchEvent
605		}
606		switch vLog.Topics[0] {
607		case logHermezL1UserTxEvent:
608			var L1UserTxAux RollupEventL1UserTxAux
609			var L1UserTx RollupEventL1UserTx
610			err := c.contractAbi.Unpack(&L1UserTxAux, "L1UserTxEvent", vLog.Data)
611			if err != nil {
612				return nil, nil, err
613			}
614			L1Tx, err := common.L1TxFromBytes(L1UserTxAux.L1Tx)
615			if err != nil {
616				return nil, nil, err
617			}
618			L1UserTx.ToForgeL1TxsNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
619			L1UserTx.Position = int(new(big.Int).SetBytes(vLog.Topics[2][:]).Int64())
620			L1UserTx.L1Tx = *L1Tx
621			rollupEvents.L1UserTx = append(rollupEvents.L1UserTx, L1UserTx)
622		case logHermezAddToken:
623			var addToken RollupEventAddToken
624			err := c.contractAbi.Unpack(&addToken, "AddToken", vLog.Data)
625			if err != nil {
626				return nil, nil, err
627			}
628			addToken.Address = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
629			rollupEvents.AddToken = append(rollupEvents.AddToken, addToken)
630		case logHermezForgeBatch:
631			var forgeBatch RollupEventForgeBatch
632			forgeBatch.BatchNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
633			forgeBatch.EthTxHash = vLog.TxHash
634			rollupEvents.ForgeBatch = append(rollupEvents.ForgeBatch, forgeBatch)
635		case logHermezUpdateForgeL1L2BatchTimeout:
636			var updateForgeL1L2BatchTimeout RollupEventUpdateForgeL1L2BatchTimeout
637			err := c.contractAbi.Unpack(&updateForgeL1L2BatchTimeout, "UpdateForgeL1L2BatchTimeout", vLog.Data)
638			if err != nil {
639				return nil, nil, err
640			}
641			rollupEvents.UpdateForgeL1L2BatchTimeout = append(rollupEvents.UpdateForgeL1L2BatchTimeout, updateForgeL1L2BatchTimeout)
642		case logHermezUpdateFeeAddToken:
643			var updateFeeAddToken RollupEventUpdateFeeAddToken
644			err := c.contractAbi.Unpack(&updateFeeAddToken, "UpdateFeeAddToken", vLog.Data)
645			if err != nil {
646				return nil, nil, err
647			}
648			rollupEvents.UpdateFeeAddToken = append(rollupEvents.UpdateFeeAddToken, updateFeeAddToken)
649		case logHermezWithdrawEvent:
650			var withdraw RollupEventWithdrawEvent
651			err := c.contractAbi.Unpack(&withdraw, "WithdrawEvent", vLog.Data)
652			if err != nil {
653				return nil, nil, err
654			}
655			withdraw.Idx = new(big.Int).SetBytes(vLog.Topics[1][:]).Uint64()
656			withdraw.NumExitRoot = new(big.Int).SetBytes(vLog.Topics[2][:]).Uint64()
657			rollupEvents.WithdrawEvent = append(rollupEvents.WithdrawEvent, withdraw)
658		}
659	}
660	return &rollupEvents, &blockHash, nil
661}
662
663// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
664func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupForgeBatchArgs, error) {
665	tx, _, err := c.client.client.TransactionByHash(context.Background(), ethTxHash)
666	if err != nil {
667		return nil, err
668	}
669	txData := tx.Data()
670	method, err := c.contractAbi.MethodById(txData[:4])
671	if err != nil {
672		return nil, err
673	}
674	var aux RollupForgeBatchArgsAux
675	if err := method.Inputs.Unpack(&aux, txData[4:]); err != nil {
676		return nil, err
677	}
678	var rollupForgeBatchArgs RollupForgeBatchArgs
679	rollupForgeBatchArgs.L1Batch = aux.L1Batch
680	rollupForgeBatchArgs.NewExitRoot = aux.NewExitRoot
681	rollupForgeBatchArgs.NewLastIdx = aux.NewLastIdx.Int64()
682	rollupForgeBatchArgs.NewStRoot = aux.NewStRoot
683	rollupForgeBatchArgs.ProofA = aux.ProofA
684	rollupForgeBatchArgs.ProofB = aux.ProofB
685	rollupForgeBatchArgs.ProofC = aux.ProofC
686	rollupForgeBatchArgs.VerifierIdx = aux.VerifierIdx
687	numTxsL1 := len(aux.EncodedL1CoordinatorTx) / common.L1CoordinatorTxBytesLen
688	for i := 0; i < numTxsL1; i++ {
689		bytesL1Coordinator := aux.EncodedL1CoordinatorTx[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen]
690		var signature []byte
691		v := bytesL1Coordinator[0]
692		s := bytesL1Coordinator[1:33]
693		r := bytesL1Coordinator[33:65]
694		signature = append(signature, r[:]...)
695		signature = append(signature, s[:]...)
696		signature = append(signature, v)
697		l1Tx, err := common.L1TxFromCoordinatorBytes(bytesL1Coordinator)
698		if err != nil {
699			return nil, err
700		}
701		rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, l1Tx)
702		rollupForgeBatchArgs.L1CoordinatorTxsAuths = append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature)
703	}
704	rollupConsts, err := c.RollupConstants()
705	if err != nil {
706		return nil, err
707	}
708	nLevels := rollupConsts.Verifiers[rollupForgeBatchArgs.VerifierIdx].NLevels
709	lenL2TxsBytes := int((nLevels/8)*2 + 2 + 1)
710	numTxsL2 := len(aux.L2TxsData) / lenL2TxsBytes
711	for i := 0; i < numTxsL2; i++ {
712		l2Tx, err := common.L2TxFromBytes(aux.L2TxsData[i*lenL2TxsBytes:(i+1)*lenL2TxsBytes], int(nLevels))
713		if err != nil {
714			return nil, err
715		}
716		rollupForgeBatchArgs.L2TxsData = append(rollupForgeBatchArgs.L2TxsData, l2Tx)
717	}
718	lenFeeIdxCoordinatorBytes := int(nLevels / 8) //nolint:gomnd
719	numFeeIdxCoordinator := len(aux.FeeIdxCoordinator) / lenFeeIdxCoordinatorBytes
720	for i := 0; i < numFeeIdxCoordinator; i++ {
721		var paddedFeeIdx [6]byte
722		// TODO: This check is not necessary: the first case will always work.  Test it before removing the if.
723		if lenFeeIdxCoordinatorBytes < common.IdxBytesLen {
724			copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
725		} else {
726			copy(paddedFeeIdx[:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
727		}
728		FeeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:])
729		if err != nil {
730			return nil, err
731		}
732		rollupForgeBatchArgs.FeeIdxCoordinator = append(rollupForgeBatchArgs.FeeIdxCoordinator, FeeIdxCoordinator)
733	}
734	return &rollupForgeBatchArgs, nil
735}