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