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.

673 lines
25 KiB

4 years ago
  1. package eth
  2. import (
  3. "context"
  4. "fmt"
  5. "math/big"
  6. "strings"
  7. "github.com/ethereum/go-ethereum"
  8. "github.com/ethereum/go-ethereum/accounts/abi"
  9. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  10. ethCommon "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/core/types"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. "github.com/ethereum/go-ethereum/ethclient"
  14. "github.com/hermeznetwork/hermez-node/common"
  15. Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez"
  16. HEZ "github.com/hermeznetwork/hermez-node/eth/contracts/tokenHEZ"
  17. "github.com/hermeznetwork/hermez-node/log"
  18. "github.com/iden3/go-iden3-crypto/babyjub"
  19. )
  20. // QueueStruct is the queue of L1Txs for a batch
  21. type QueueStruct struct {
  22. L1TxQueue []common.L1Tx
  23. TotalL1TxFee *big.Int
  24. }
  25. // NewQueueStruct creates a new clear QueueStruct.
  26. func NewQueueStruct() *QueueStruct {
  27. return &QueueStruct{
  28. L1TxQueue: make([]common.L1Tx, 0),
  29. TotalL1TxFee: big.NewInt(0),
  30. }
  31. }
  32. // RollupState represents the state of the Rollup in the Smart Contract
  33. type RollupState struct {
  34. StateRoot *big.Int
  35. ExitRoots []*big.Int
  36. ExitNullifierMap map[[256 / 8]byte]bool
  37. TokenList []ethCommon.Address
  38. TokenMap map[ethCommon.Address]bool
  39. MapL1TxQueue map[int64]*QueueStruct
  40. LastL1L2Batch int64
  41. CurrentToForgeL1TxsNum int64
  42. LastToForgeL1TxsNum int64
  43. CurrentIdx int64
  44. }
  45. // RollupEventL1UserTx is an event of the Rollup Smart Contract
  46. type RollupEventL1UserTx struct {
  47. // ToForgeL1TxsNum int64 // QueueIndex *big.Int
  48. // Position int // TransactionIndex *big.Int
  49. L1UserTx common.L1Tx
  50. }
  51. // RollupEventL1UserTxAux is an event of the Rollup Smart Contract
  52. type RollupEventL1UserTxAux struct {
  53. ToForgeL1TxsNum uint64 // QueueIndex *big.Int
  54. Position uint8 // TransactionIndex *big.Int
  55. L1UserTx []byte
  56. }
  57. // RollupEventAddToken is an event of the Rollup Smart Contract
  58. type RollupEventAddToken struct {
  59. TokenAddress ethCommon.Address
  60. TokenID uint32
  61. }
  62. // RollupEventForgeBatch is an event of the Rollup Smart Contract
  63. type RollupEventForgeBatch struct {
  64. BatchNum int64
  65. // Sender ethCommon.Address
  66. EthTxHash ethCommon.Hash
  67. }
  68. // RollupEventUpdateForgeL1L2BatchTimeout is an event of the Rollup Smart Contract
  69. type RollupEventUpdateForgeL1L2BatchTimeout struct {
  70. NewForgeL1L2BatchTimeout int64
  71. }
  72. // RollupEventUpdateFeeAddToken is an event of the Rollup Smart Contract
  73. type RollupEventUpdateFeeAddToken struct {
  74. NewFeeAddToken *big.Int
  75. }
  76. // RollupEventWithdraw is an event of the Rollup Smart Contract
  77. type RollupEventWithdraw struct {
  78. Idx uint64
  79. NumExitRoot uint64
  80. InstantWithdraw bool
  81. }
  82. // RollupEvents is the list of events in a block of the Rollup Smart Contract
  83. type RollupEvents struct {
  84. L1UserTx []RollupEventL1UserTx
  85. AddToken []RollupEventAddToken
  86. ForgeBatch []RollupEventForgeBatch
  87. UpdateForgeL1L2BatchTimeout []RollupEventUpdateForgeL1L2BatchTimeout
  88. UpdateFeeAddToken []RollupEventUpdateFeeAddToken
  89. Withdraw []RollupEventWithdraw
  90. }
  91. // NewRollupEvents creates an empty RollupEvents with the slices initialized.
  92. func NewRollupEvents() RollupEvents {
  93. return RollupEvents{
  94. L1UserTx: make([]RollupEventL1UserTx, 0),
  95. AddToken: make([]RollupEventAddToken, 0),
  96. ForgeBatch: make([]RollupEventForgeBatch, 0),
  97. UpdateForgeL1L2BatchTimeout: make([]RollupEventUpdateForgeL1L2BatchTimeout, 0),
  98. UpdateFeeAddToken: make([]RollupEventUpdateFeeAddToken, 0),
  99. Withdraw: make([]RollupEventWithdraw, 0),
  100. }
  101. }
  102. // RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
  103. type RollupForgeBatchArgs struct {
  104. NewLastIdx int64
  105. NewStRoot *big.Int
  106. NewExitRoot *big.Int
  107. L1CoordinatorTxs []common.L1Tx
  108. L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx
  109. L2TxsData []common.L2Tx
  110. FeeIdxCoordinator []common.Idx
  111. // Circuit selector
  112. VerifierIdx uint8
  113. L1Batch bool
  114. ProofA [2]*big.Int
  115. ProofB [2][2]*big.Int
  116. ProofC [2]*big.Int
  117. }
  118. // RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract
  119. type RollupForgeBatchArgsAux struct {
  120. NewLastIdx *big.Int
  121. NewStRoot *big.Int
  122. NewExitRoot *big.Int
  123. EncodedL1CoordinatorTx []byte
  124. L2TxsData []byte
  125. FeeIdxCoordinator []byte
  126. // Circuit selector
  127. VerifierIdx uint8
  128. L1Batch bool
  129. ProofA [2]*big.Int
  130. ProofB [2][2]*big.Int
  131. ProofC [2]*big.Int
  132. }
  133. // RollupInterface is the inteface to to Rollup Smart Contract
  134. type RollupInterface interface {
  135. //
  136. // Smart Contract Methods
  137. //
  138. // Public Functions
  139. RollupForgeBatch(*RollupForgeBatchArgs) (*types.Transaction, error)
  140. RollupAddToken(tokenAddress ethCommon.Address, feeAddToken, deadline *big.Int) (*types.Transaction, error)
  141. RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction, error)
  142. RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int, tokenID uint32, numExitRoot, idx int64, amount *big.Int, instantWithdraw bool) (*types.Transaction, error)
  143. RollupL1UserTxERC20ETH(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error)
  144. RollupL1UserTxERC20Permit(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64, deadline *big.Int) (tx *types.Transaction, err error)
  145. // Governance Public Functions
  146. RollupUpdateForgeL1L2BatchTimeout(newForgeL1L2BatchTimeout int64) (*types.Transaction, error)
  147. RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error)
  148. // Viewers
  149. RollupRegisterTokensCount() (*big.Int, error)
  150. //
  151. // Smart Contract Status
  152. //
  153. RollupConstants() (*common.RollupConstants, error)
  154. RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error)
  155. RollupForgeBatchArgs(ethCommon.Hash) (*RollupForgeBatchArgs, *ethCommon.Address, error)
  156. }
  157. //
  158. // Implementation
  159. //
  160. // RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum.
  161. type RollupClient struct {
  162. client *EthereumClient
  163. address ethCommon.Address
  164. tokenHEZCfg TokenConfig
  165. hermez *Hermez.Hermez
  166. tokenHEZ *HEZ.HEZ
  167. contractAbi abi.ABI
  168. }
  169. // NewRollupClient creates a new RollupClient
  170. func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenHEZCfg TokenConfig) (*RollupClient, error) {
  171. contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI)))
  172. if err != nil {
  173. return nil, err
  174. }
  175. hermez, err := Hermez.NewHermez(address, client.Client())
  176. if err != nil {
  177. return nil, err
  178. }
  179. tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
  180. if err != nil {
  181. return nil, err
  182. }
  183. return &RollupClient{
  184. client: client,
  185. address: address,
  186. tokenHEZCfg: tokenHEZCfg,
  187. hermez: hermez,
  188. tokenHEZ: tokenHEZ,
  189. contractAbi: contractAbi,
  190. }, nil
  191. }
  192. // RollupForgeBatch is the interface to call the smart contract function
  193. func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (tx *types.Transaction, err error) {
  194. if tx, err = c.client.CallAuth(
  195. 1000000, //nolint:gomnd
  196. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  197. rollupConst, err := c.RollupConstants()
  198. if err != nil {
  199. return nil, err
  200. }
  201. nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels
  202. lenBytes := nLevels / 8 //nolint:gomnd
  203. newLastIdx := big.NewInt(int64(args.NewLastIdx))
  204. var l1CoordinatorBytes []byte
  205. for i := 0; i < len(args.L1CoordinatorTxs); i++ {
  206. l1 := args.L1CoordinatorTxs[i]
  207. bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i])
  208. if err != nil {
  209. return nil, err
  210. }
  211. l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...)
  212. }
  213. var l2DataBytes []byte
  214. for i := 0; i < len(args.L2TxsData); i++ {
  215. l2 := args.L2TxsData[i]
  216. bytesl2, err := l2.Bytes(int(nLevels))
  217. if err != nil {
  218. return nil, err
  219. }
  220. l2DataBytes = append(l2DataBytes, bytesl2[:]...)
  221. }
  222. var feeIdxCoordinator []byte
  223. if len(args.FeeIdxCoordinator) > common.RollupConstMaxFeeIdxCoordinator {
  224. return nil, fmt.Errorf("len(args.FeeIdxCoordinator) > %v",
  225. common.RollupConstMaxFeeIdxCoordinator)
  226. }
  227. for i := 0; i < common.RollupConstMaxFeeIdxCoordinator; i++ {
  228. feeIdx := common.Idx(0)
  229. if i < len(args.FeeIdxCoordinator) {
  230. feeIdx = args.FeeIdxCoordinator[i]
  231. }
  232. bytesFeeIdx, err := feeIdx.Bytes()
  233. if err != nil {
  234. return nil, err
  235. }
  236. feeIdxCoordinator = append(feeIdxCoordinator, bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...)
  237. }
  238. return c.hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot, l1CoordinatorBytes, l2DataBytes, feeIdxCoordinator, args.VerifierIdx, args.L1Batch, args.ProofA, args.ProofB, args.ProofC)
  239. },
  240. ); err != nil {
  241. return nil, fmt.Errorf("Failed forge batch: %w", err)
  242. }
  243. return tx, nil
  244. }
  245. // RollupAddToken is the interface to call the smart contract function.
  246. // `feeAddToken` is the amount of HEZ tokens that will be paid to add the
  247. // token. `feeAddToken` must match the public value of the smart contract.
  248. func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken, deadline *big.Int) (tx *types.Transaction, err error) {
  249. if tx, err = c.client.CallAuth(
  250. 0,
  251. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  252. owner := c.client.account.Address
  253. spender := c.address
  254. nonce, err := c.tokenHEZ.Nonces(nil, owner)
  255. if err != nil {
  256. return nil, err
  257. }
  258. tokenName := c.tokenHEZCfg.Name
  259. tokenAddr := c.tokenHEZCfg.Address
  260. chainid, _ := c.client.Client().ChainID(context.Background())
  261. digest, _ := createPermitDigest(tokenAddr, owner, spender, chainid, feeAddToken, nonce, deadline, tokenName)
  262. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  263. permit := createPermit(owner, spender, feeAddToken, deadline, digest, signature)
  264. return c.hermez.AddToken(auth, tokenAddress, permit)
  265. },
  266. ); err != nil {
  267. return nil, fmt.Errorf("Failed add Token %w", err)
  268. }
  269. return tx, nil
  270. }
  271. // RollupWithdrawMerkleProof is the interface to call the smart contract function
  272. 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) {
  273. if tx, err = c.client.CallAuth(
  274. 0,
  275. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  276. pkCompL := fromBJJ.Compress()
  277. pkCompB := common.SwapEndianness(pkCompL[:])
  278. babyPubKey := new(big.Int).SetBytes(pkCompB)
  279. numExitRootB := big.NewInt(numExitRoot)
  280. idxBig := big.NewInt(idx)
  281. return c.hermez.WithdrawMerkleProof(auth, tokenID, amount, babyPubKey, numExitRootB, siblings, idxBig, instantWithdraw)
  282. },
  283. ); err != nil {
  284. return nil, fmt.Errorf("Failed update WithdrawMerkleProof: %w", err)
  285. }
  286. return tx, nil
  287. }
  288. // RollupWithdrawCircuit is the interface to call the smart contract function
  289. 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) {
  290. log.Error("TODO")
  291. return nil, errTODO
  292. }
  293. // RollupL1UserTxERC20ETH is the interface to call the smart contract function
  294. func (c *RollupClient) RollupL1UserTxERC20ETH(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (tx *types.Transaction, err error) {
  295. if tx, err = c.client.CallAuth(
  296. 0,
  297. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  298. pkCompL := fromBJJ.Compress()
  299. pkCompB := common.SwapEndianness(pkCompL[:])
  300. babyPubKey := new(big.Int).SetBytes(pkCompB)
  301. fromIdxBig := big.NewInt(fromIdx)
  302. toIdxBig := big.NewInt(toIdx)
  303. loadAmountF, err := common.NewFloat16(loadAmount)
  304. if err != nil {
  305. return nil, err
  306. }
  307. amountF, err := common.NewFloat16(amount)
  308. if err != nil {
  309. return nil, err
  310. }
  311. if tokenID == 0 {
  312. auth.Value = loadAmount
  313. }
  314. var permit []byte
  315. return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig, uint16(loadAmountF),
  316. uint16(amountF), tokenID, toIdxBig, permit)
  317. },
  318. ); err != nil {
  319. return nil, fmt.Errorf("Failed add L1 Tx ERC20/ETH: %w", err)
  320. }
  321. return tx, nil
  322. }
  323. // RollupL1UserTxERC20Permit is the interface to call the smart contract function
  324. func (c *RollupClient) RollupL1UserTxERC20Permit(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64, deadline *big.Int) (tx *types.Transaction, err error) {
  325. if tx, err = c.client.CallAuth(
  326. 0,
  327. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  328. pkCompL := fromBJJ.Compress()
  329. pkCompB := common.SwapEndianness(pkCompL[:])
  330. babyPubKey := new(big.Int).SetBytes(pkCompB)
  331. fromIdxBig := big.NewInt(fromIdx)
  332. toIdxBig := big.NewInt(toIdx)
  333. loadAmountF, err := common.NewFloat16(loadAmount)
  334. if err != nil {
  335. return nil, err
  336. }
  337. amountF, err := common.NewFloat16(amount)
  338. if err != nil {
  339. return nil, err
  340. }
  341. if tokenID == 0 {
  342. auth.Value = loadAmount
  343. }
  344. owner := c.client.account.Address
  345. spender := c.address
  346. nonce, err := c.tokenHEZ.Nonces(nil, owner)
  347. if err != nil {
  348. return nil, err
  349. }
  350. tokenName := c.tokenHEZCfg.Name
  351. tokenAddr := c.tokenHEZCfg.Address
  352. chainid, _ := c.client.Client().ChainID(context.Background())
  353. digest, _ := createPermitDigest(tokenAddr, owner, spender, chainid, amount, nonce, deadline, tokenName)
  354. signature, _ := c.client.ks.SignHash(*c.client.account, digest)
  355. permit := createPermit(owner, spender, amount, deadline, digest, signature)
  356. return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig, uint16(loadAmountF),
  357. uint16(amountF), tokenID, toIdxBig, permit)
  358. },
  359. ); err != nil {
  360. return nil, fmt.Errorf("Failed add L1 Tx ERC20Permit: %w", err)
  361. }
  362. return tx, nil
  363. }
  364. // RollupRegisterTokensCount is the interface to call the smart contract function
  365. func (c *RollupClient) RollupRegisterTokensCount() (*big.Int, error) {
  366. var registerTokensCount *big.Int
  367. if err := c.client.Call(func(ec *ethclient.Client) error {
  368. hermez, err := Hermez.NewHermez(c.address, ec)
  369. if err != nil {
  370. return err
  371. }
  372. registerTokensCount, err = hermez.RegisterTokensCount(nil)
  373. return err
  374. }); err != nil {
  375. return nil, err
  376. }
  377. return registerTokensCount, nil
  378. }
  379. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  380. func (c *RollupClient) RollupUpdateForgeL1L2BatchTimeout(newForgeL1L2BatchTimeout int64) (tx *types.Transaction, err error) {
  381. if tx, err = c.client.CallAuth(
  382. 0,
  383. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  384. return c.hermez.UpdateForgeL1L2BatchTimeout(auth, uint8(newForgeL1L2BatchTimeout))
  385. },
  386. ); err != nil {
  387. return nil, fmt.Errorf("Failed update ForgeL1L2BatchTimeout: %w", err)
  388. }
  389. return tx, nil
  390. }
  391. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  392. func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
  393. if tx, err = c.client.CallAuth(
  394. 0,
  395. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  396. return c.hermez.UpdateFeeAddToken(auth, newFeeAddToken)
  397. },
  398. ); err != nil {
  399. return nil, fmt.Errorf("Failed update FeeAddToken: %w", err)
  400. }
  401. return tx, nil
  402. }
  403. // RollupConstants returns the Constants of the Rollup Smart Contract
  404. func (c *RollupClient) RollupConstants() (rollupConstants *common.RollupConstants, err error) {
  405. rollupConstants = new(common.RollupConstants)
  406. if err := c.client.Call(func(ec *ethclient.Client) error {
  407. absoluteMaxL1L2BatchTimeout, err := c.hermez.ABSOLUTEMAXL1L2BATCHTIMEOUT(nil)
  408. if err != nil {
  409. return err
  410. }
  411. rollupConstants.AbsoluteMaxL1L2BatchTimeout = int64(absoluteMaxL1L2BatchTimeout)
  412. rollupConstants.TokenHEZ, err = c.hermez.TokenHEZ(nil)
  413. if err != nil {
  414. return err
  415. }
  416. for i := int64(0); i < int64(common.LenVerifiers); i++ {
  417. var newRollupVerifier common.RollupVerifierStruct
  418. rollupVerifier, err := c.hermez.RollupVerifiers(nil, big.NewInt(i))
  419. if err != nil {
  420. return err
  421. }
  422. newRollupVerifier.MaxTx = rollupVerifier.MaxTx.Int64()
  423. newRollupVerifier.NLevels = rollupVerifier.NLevels.Int64()
  424. rollupConstants.Verifiers = append(rollupConstants.Verifiers, newRollupVerifier)
  425. }
  426. rollupConstants.HermezAuctionContract, err = c.hermez.HermezAuctionContract(nil)
  427. if err != nil {
  428. return err
  429. }
  430. rollupConstants.HermezGovernanceDAOAddress, err = c.hermez.HermezGovernanceDAOAddress(nil)
  431. if err != nil {
  432. return err
  433. }
  434. rollupConstants.SafetyAddress, err = c.hermez.SafetyAddress(nil)
  435. if err != nil {
  436. return err
  437. }
  438. rollupConstants.WithdrawDelayerContract, err = c.hermez.WithdrawDelayerContract(nil)
  439. return err
  440. }); err != nil {
  441. return nil, err
  442. }
  443. return rollupConstants, nil
  444. }
  445. var (
  446. logHermezL1UserTxEvent = crypto.Keccak256Hash([]byte("L1UserTxEvent(uint64,uint8,bytes)"))
  447. logHermezAddToken = crypto.Keccak256Hash([]byte("AddToken(address,uint32)"))
  448. logHermezForgeBatch = crypto.Keccak256Hash([]byte("ForgeBatch(uint64)"))
  449. logHermezUpdateForgeL1L2BatchTimeout = crypto.Keccak256Hash([]byte("UpdateForgeL1L2BatchTimeout(uint8)"))
  450. logHermezUpdateFeeAddToken = crypto.Keccak256Hash([]byte("UpdateFeeAddToken(uint256)"))
  451. logHermezWithdrawEvent = crypto.Keccak256Hash([]byte("WithdrawEvent(uint48,uint48,bool)"))
  452. )
  453. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  454. func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error) {
  455. var rollupEvents RollupEvents
  456. var blockHash *ethCommon.Hash
  457. query := ethereum.FilterQuery{
  458. FromBlock: big.NewInt(blockNum),
  459. ToBlock: big.NewInt(blockNum),
  460. Addresses: []ethCommon.Address{
  461. c.address,
  462. },
  463. BlockHash: nil,
  464. Topics: [][]ethCommon.Hash{},
  465. }
  466. logs, err := c.client.client.FilterLogs(context.Background(), query)
  467. if err != nil {
  468. return nil, nil, err
  469. }
  470. if len(logs) > 0 {
  471. blockHash = &logs[0].BlockHash
  472. }
  473. for _, vLog := range logs {
  474. if vLog.BlockHash != *blockHash {
  475. log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
  476. return nil, nil, ErrBlockHashMismatchEvent
  477. }
  478. switch vLog.Topics[0] {
  479. case logHermezL1UserTxEvent:
  480. var L1UserTxAux RollupEventL1UserTxAux
  481. var L1UserTx RollupEventL1UserTx
  482. err := c.contractAbi.Unpack(&L1UserTxAux, "L1UserTxEvent", vLog.Data)
  483. if err != nil {
  484. return nil, nil, err
  485. }
  486. L1Tx, err := common.L1UserTxFromBytes(L1UserTxAux.L1UserTx)
  487. if err != nil {
  488. return nil, nil, err
  489. }
  490. toForgeL1TxsNum := new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  491. L1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum
  492. L1Tx.Position = int(new(big.Int).SetBytes(vLog.Topics[2][:]).Int64())
  493. L1Tx.UserOrigin = true
  494. L1UserTx.L1UserTx = *L1Tx
  495. rollupEvents.L1UserTx = append(rollupEvents.L1UserTx, L1UserTx)
  496. case logHermezAddToken:
  497. var addToken RollupEventAddToken
  498. err := c.contractAbi.Unpack(&addToken, "AddToken", vLog.Data)
  499. if err != nil {
  500. return nil, nil, err
  501. }
  502. addToken.TokenAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  503. rollupEvents.AddToken = append(rollupEvents.AddToken, addToken)
  504. case logHermezForgeBatch:
  505. var forgeBatch RollupEventForgeBatch
  506. forgeBatch.BatchNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  507. forgeBatch.EthTxHash = vLog.TxHash
  508. // forgeBatch.Sender = vLog.Address
  509. rollupEvents.ForgeBatch = append(rollupEvents.ForgeBatch, forgeBatch)
  510. case logHermezUpdateForgeL1L2BatchTimeout:
  511. var updateForgeL1L2BatchTimeout struct {
  512. NewForgeL1L2BatchTimeout uint8
  513. }
  514. err := c.contractAbi.Unpack(&updateForgeL1L2BatchTimeout, "UpdateForgeL1L2BatchTimeout", vLog.Data)
  515. if err != nil {
  516. return nil, nil, err
  517. }
  518. rollupEvents.UpdateForgeL1L2BatchTimeout = append(rollupEvents.UpdateForgeL1L2BatchTimeout,
  519. RollupEventUpdateForgeL1L2BatchTimeout{
  520. NewForgeL1L2BatchTimeout: int64(updateForgeL1L2BatchTimeout.NewForgeL1L2BatchTimeout),
  521. })
  522. case logHermezUpdateFeeAddToken:
  523. var updateFeeAddToken RollupEventUpdateFeeAddToken
  524. err := c.contractAbi.Unpack(&updateFeeAddToken, "UpdateFeeAddToken", vLog.Data)
  525. if err != nil {
  526. return nil, nil, err
  527. }
  528. rollupEvents.UpdateFeeAddToken = append(rollupEvents.UpdateFeeAddToken, updateFeeAddToken)
  529. case logHermezWithdrawEvent:
  530. var withdraw RollupEventWithdraw
  531. withdraw.Idx = new(big.Int).SetBytes(vLog.Topics[1][:]).Uint64()
  532. withdraw.NumExitRoot = new(big.Int).SetBytes(vLog.Topics[2][:]).Uint64()
  533. instantWithdraw := new(big.Int).SetBytes(vLog.Topics[3][:]).Uint64()
  534. if instantWithdraw == 1 {
  535. withdraw.InstantWithdraw = true
  536. }
  537. rollupEvents.Withdraw = append(rollupEvents.Withdraw, withdraw)
  538. }
  539. }
  540. return &rollupEvents, blockHash, nil
  541. }
  542. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the
  543. // Rollup Smart Contract in the given transaction, and the sender address.
  544. func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupForgeBatchArgs, *ethCommon.Address, error) {
  545. tx, _, err := c.client.client.TransactionByHash(context.Background(), ethTxHash)
  546. if err != nil {
  547. return nil, nil, err
  548. }
  549. txData := tx.Data()
  550. method, err := c.contractAbi.MethodById(txData[:4])
  551. if err != nil {
  552. return nil, nil, err
  553. }
  554. receipt, err := c.client.client.TransactionReceipt(context.Background(), ethTxHash)
  555. if err != nil {
  556. return nil, nil, err
  557. }
  558. sender, err := c.client.client.TransactionSender(context.Background(), tx, receipt.Logs[0].BlockHash, receipt.Logs[0].Index)
  559. if err != nil {
  560. return nil, nil, err
  561. }
  562. var aux RollupForgeBatchArgsAux
  563. if err := method.Inputs.Unpack(&aux, txData[4:]); err != nil {
  564. return nil, nil, err
  565. }
  566. rollupForgeBatchArgs := RollupForgeBatchArgs{
  567. L1Batch: aux.L1Batch,
  568. NewExitRoot: aux.NewExitRoot,
  569. NewLastIdx: aux.NewLastIdx.Int64(),
  570. NewStRoot: aux.NewStRoot,
  571. ProofA: aux.ProofA,
  572. ProofB: aux.ProofB,
  573. ProofC: aux.ProofC,
  574. VerifierIdx: aux.VerifierIdx,
  575. L1CoordinatorTxs: []common.L1Tx{},
  576. L1CoordinatorTxsAuths: [][]byte{},
  577. L2TxsData: []common.L2Tx{},
  578. FeeIdxCoordinator: []common.Idx{},
  579. }
  580. numTxsL1 := len(aux.EncodedL1CoordinatorTx) / common.L1CoordinatorTxBytesLen
  581. for i := 0; i < numTxsL1; i++ {
  582. bytesL1Coordinator := aux.EncodedL1CoordinatorTx[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen]
  583. var signature []byte
  584. v := bytesL1Coordinator[0]
  585. s := bytesL1Coordinator[1:33]
  586. r := bytesL1Coordinator[33:65]
  587. signature = append(signature, r[:]...)
  588. signature = append(signature, s[:]...)
  589. signature = append(signature, v)
  590. l1Tx, err := common.L1CoordinatorTxFromBytes(bytesL1Coordinator)
  591. if err != nil {
  592. return nil, nil, err
  593. }
  594. rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, *l1Tx)
  595. rollupForgeBatchArgs.L1CoordinatorTxsAuths = append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature)
  596. }
  597. rollupConsts, err := c.RollupConstants()
  598. if err != nil {
  599. return nil, nil, err
  600. }
  601. nLevels := rollupConsts.Verifiers[rollupForgeBatchArgs.VerifierIdx].NLevels
  602. lenL2TxsBytes := int((nLevels/8)*2 + 2 + 1)
  603. numTxsL2 := len(aux.L2TxsData) / lenL2TxsBytes
  604. for i := 0; i < numTxsL2; i++ {
  605. l2Tx, err := common.L2TxFromBytes(aux.L2TxsData[i*lenL2TxsBytes:(i+1)*lenL2TxsBytes], int(nLevels))
  606. if err != nil {
  607. return nil, nil, err
  608. }
  609. rollupForgeBatchArgs.L2TxsData = append(rollupForgeBatchArgs.L2TxsData, *l2Tx)
  610. }
  611. lenFeeIdxCoordinatorBytes := int(nLevels / 8) //nolint:gomnd
  612. numFeeIdxCoordinator := len(aux.FeeIdxCoordinator) / lenFeeIdxCoordinatorBytes
  613. for i := 0; i < numFeeIdxCoordinator; i++ {
  614. var paddedFeeIdx [6]byte
  615. // TODO: This check is not necessary: the first case will always work. Test it before removing the if.
  616. if lenFeeIdxCoordinatorBytes < common.IdxBytesLen {
  617. copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
  618. } else {
  619. copy(paddedFeeIdx[:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
  620. }
  621. feeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:])
  622. if err != nil {
  623. return nil, nil, err
  624. }
  625. if feeIdxCoordinator != common.Idx(0) {
  626. rollupForgeBatchArgs.FeeIdxCoordinator = append(rollupForgeBatchArgs.FeeIdxCoordinator, feeIdxCoordinator)
  627. }
  628. }
  629. return &rollupForgeBatchArgs, &sender, nil
  630. }