You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

967 lines
37 KiB

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