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