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.

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