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.

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