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.

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