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.

913 lines
35 KiB

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