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.

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