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.

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