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.

801 lines
31 KiB

4 years ago
  1. package eth
  2. import (
  3. "context"
  4. "fmt"
  5. "math/big"
  6. "strings"
  7. "github.com/ethereum/go-ethereum"
  8. "github.com/ethereum/go-ethereum/accounts/abi"
  9. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  10. ethCommon "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/core/types"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. "github.com/ethereum/go-ethereum/ethclient"
  14. "github.com/hermeznetwork/hermez-node/common"
  15. ERC777 "github.com/hermeznetwork/hermez-node/eth/contracts/erc777"
  16. Hermez "github.com/hermeznetwork/hermez-node/eth/contracts/hermez"
  17. "github.com/hermeznetwork/hermez-node/log"
  18. "github.com/iden3/go-iden3-crypto/babyjub"
  19. "golang.org/x/crypto/sha3"
  20. )
  21. const (
  22. // RollupConstMaxFeeIdxCoordinator is the maximum number of tokens the
  23. // coordinator can use to collect fees (determines the number of tokens
  24. // that the coordinator can collect fees from). This value is
  25. // determined by the circuit.
  26. RollupConstMaxFeeIdxCoordinator = 64
  27. // RollupConstReservedIDx First 256 indexes reserved, first user index will be the 256
  28. RollupConstReservedIDx = 255
  29. // RollupConstExitIDx IDX 1 is reserved for exits
  30. RollupConstExitIDx = 1
  31. // RollupConstLimitLoadAmount Max load amount allowed (loadAmount: L1 --> L2)
  32. RollupConstLimitLoadAmount = (1 << 128)
  33. // RollupConstLimitL2TransferAmount Max amount allowed (amount L2 --> L2)
  34. RollupConstLimitL2TransferAmount = (1 << 192)
  35. // RollupConstLimitTokens Max number of tokens allowed to be registered inside the rollup
  36. RollupConstLimitTokens = (1 << 32)
  37. // RollupConstL1CoordinatorTotalBytes [4 bytes] token + [32 bytes] babyjub + [65 bytes] compressedSignature
  38. RollupConstL1CoordinatorTotalBytes = 101
  39. // RollupConstL1UserTotalBytes [20 bytes] fromEthAddr + [32 bytes] fromBjj-compressed + [6 bytes] fromIdx +
  40. // [2 bytes] loadAmountFloat16 + [2 bytes] amountFloat16 + [4 bytes] tokenId + [6 bytes] toIdx
  41. RollupConstL1UserTotalBytes = 72
  42. // RollupConstMaxL1UserTx Maximum L1-user transactions allowed to be queued in a batch
  43. RollupConstMaxL1UserTx = 128
  44. // RollupConstMaxL1Tx Maximum L1 transactions allowed to be queued in a batch
  45. RollupConstMaxL1Tx = 256
  46. // RollupConstInputSHAConstantBytes [6 bytes] lastIdx + [6 bytes] newLastIdx + [32 bytes] stateRoot + [32 bytes] newStRoot + [32 bytes] newExitRoot +
  47. // [_MAX_L1_TX * _L1_USER_TOTALBYTES bytes] l1TxsData + totalL2TxsDataLength + feeIdxCoordinatorLength + [2 bytes] chainID =
  48. // 18542 bytes + totalL2TxsDataLength + feeIdxCoordinatorLength
  49. RollupConstInputSHAConstantBytes = 18542
  50. // RollupConstNumBuckets Number of buckets
  51. RollupConstNumBuckets = 5
  52. // RollupConstMaxWithdrawalDelay max withdrawal delay in seconds
  53. RollupConstMaxWithdrawalDelay = 2 * 7 * 24 * 60 * 60
  54. // RollupConstExchangeMultiplier exchange multiplier
  55. RollupConstExchangeMultiplier = 1e14
  56. // LenVerifiers number of Rollup Smart Contract Verifiers
  57. LenVerifiers = 1
  58. )
  59. var (
  60. // RollupConstEthAddressInternalOnly This ethereum address is used internally for rollup accounts that don't have ethereum address, only Babyjubjub
  61. // This non-ethereum accounts can be created by the coordinator and allow users to have a rollup
  62. // account without needing an ethereum address
  63. RollupConstEthAddressInternalOnly = ethCommon.HexToAddress("0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF")
  64. // RollupConstRfield Modulus zkSNARK
  65. RollupConstRfield, _ = new(big.Int).SetString(
  66. "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
  67. // RollupConstERC1820 ERC1820Registry address
  68. RollupConstERC1820 = ethCommon.HexToAddress("0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24")
  69. // ERC777 tokens signatures
  70. // RollupConstRecipientInterfaceHash ERC777 recipient interface hash
  71. RollupConstRecipientInterfaceHash = crypto.Keccak256([]byte("ERC777TokensRecipient"))
  72. // RollupConstPerformL1UserTxSignature the signature of the function that can be called thru an ERC777 `send`
  73. RollupConstPerformL1UserTxSignature = crypto.Keccak256([]byte("addL1Transaction(uint256,uint48,uint16,uint16,uint32,uint48)"))
  74. // RollupConstAddTokenSignature the signature of the function that can be called thru an ERC777 `send`
  75. RollupConstAddTokenSignature = crypto.Keccak256([]byte("addToken(address)"))
  76. // RollupConstSendSignature ERC777 Signature
  77. RollupConstSendSignature = crypto.Keccak256([]byte("send(address,uint256,bytes)"))
  78. // RollupConstERC777Granularity ERC777 Signature
  79. RollupConstERC777Granularity = crypto.Keccak256([]byte("granularity()"))
  80. // RollupConstWithdrawalDelayerDeposit This constant are used to deposit tokens from ERC77 tokens into withdrawal delayer
  81. RollupConstWithdrawalDelayerDeposit = crypto.Keccak256([]byte("deposit(address,address,uint192)"))
  82. // ERC20 signature
  83. // RollupConstTransferSignature This constant is used in the _safeTransfer internal method in order to safe GAS.
  84. RollupConstTransferSignature = crypto.Keccak256([]byte("transfer(address,uint256)"))
  85. // RollupConstTransferFromSignature This constant is used in the _safeTransfer internal method in order to safe GAS.
  86. RollupConstTransferFromSignature = crypto.Keccak256([]byte("transferFrom(address,address,uint256)"))
  87. // RollupConstApproveSignature This constant is used in the _safeTransfer internal method in order to safe GAS.
  88. RollupConstApproveSignature = crypto.Keccak256([]byte("approve(address,uint256)"))
  89. // RollupConstERC20Signature ERC20 decimals signature
  90. RollupConstERC20Signature = crypto.Keccak256([]byte("decimals()"))
  91. )
  92. // RollupPublicConstants are the constants of the Rollup Smart Contract
  93. type RollupPublicConstants struct {
  94. AbsoluteMaxL1L2BatchTimeout int64 `json:"absoluteMaxL1L2BatchTimeout"`
  95. TokenHEZ ethCommon.Address `json:"tokenHEZ"`
  96. Verifiers []RollupVerifierStruct `json:"verifiers"`
  97. HermezAuctionContract ethCommon.Address `json:"hermezAuctionContract"`
  98. HermezGovernanceDAOAddress ethCommon.Address `json:"hermezGovernanceDAOAddress"`
  99. SafetyAddress ethCommon.Address `json:"safetyAddress"`
  100. WithdrawDelayerContract ethCommon.Address `json:"withdrawDelayerContract"`
  101. }
  102. // RollupVariables are the variables of the Rollup Smart Contract
  103. type RollupVariables struct {
  104. FeeAddToken *big.Int
  105. ForgeL1L2BatchTimeout int64
  106. WithdrawalDelay uint64
  107. }
  108. // QueueStruct is the queue of L1Txs for a batch
  109. type QueueStruct struct {
  110. L1TxQueue []common.L1Tx
  111. TotalL1TxFee *big.Int
  112. }
  113. // NewQueueStruct creates a new clear QueueStruct.
  114. func NewQueueStruct() *QueueStruct {
  115. return &QueueStruct{
  116. L1TxQueue: make([]common.L1Tx, 0),
  117. TotalL1TxFee: big.NewInt(0),
  118. }
  119. }
  120. // RollupVerifierStruct is the information about verifiers of the Rollup Smart Contract
  121. type RollupVerifierStruct struct {
  122. MaxTx int64 `json:"maxTx"`
  123. NLevels int64 `json:"nlevels"`
  124. }
  125. // RollupState represents the state of the Rollup in the Smart Contract
  126. type RollupState struct {
  127. StateRoot *big.Int
  128. ExitRoots []*big.Int
  129. ExitNullifierMap map[[256 / 8]byte]bool
  130. TokenList []ethCommon.Address
  131. TokenMap map[ethCommon.Address]bool
  132. MapL1TxQueue map[int64]*QueueStruct
  133. LastL1L2Batch int64
  134. CurrentToForgeL1TxsNum int64
  135. LastToForgeL1TxsNum int64
  136. CurrentIdx int64
  137. }
  138. // RollupEventL1UserTx is an event of the Rollup Smart Contract
  139. type RollupEventL1UserTx struct {
  140. // ToForgeL1TxsNum int64 // QueueIndex *big.Int
  141. // Position int // TransactionIndex *big.Int
  142. L1UserTx common.L1Tx
  143. }
  144. // RollupEventL1UserTxAux is an event of the Rollup Smart Contract
  145. type RollupEventL1UserTxAux struct {
  146. ToForgeL1TxsNum uint64 // QueueIndex *big.Int
  147. Position uint8 // TransactionIndex *big.Int
  148. L1UserTx []byte
  149. }
  150. // RollupEventAddToken is an event of the Rollup Smart Contract
  151. type RollupEventAddToken struct {
  152. TokenAddress ethCommon.Address
  153. TokenID uint32
  154. }
  155. // RollupEventForgeBatch is an event of the Rollup Smart Contract
  156. type RollupEventForgeBatch struct {
  157. BatchNum int64
  158. // Sender ethCommon.Address
  159. EthTxHash ethCommon.Hash
  160. }
  161. // RollupEventUpdateForgeL1L2BatchTimeout is an event of the Rollup Smart Contract
  162. type RollupEventUpdateForgeL1L2BatchTimeout struct {
  163. NewForgeL1L2BatchTimeout int64
  164. }
  165. // RollupEventUpdateFeeAddToken is an event of the Rollup Smart Contract
  166. type RollupEventUpdateFeeAddToken struct {
  167. NewFeeAddToken *big.Int
  168. }
  169. // RollupEventWithdrawEvent is an event of the Rollup Smart Contract
  170. type RollupEventWithdrawEvent struct {
  171. Idx uint64
  172. NumExitRoot uint64
  173. InstantWithdraw bool
  174. }
  175. // RollupEvents is the list of events in a block of the Rollup Smart Contract
  176. type RollupEvents struct {
  177. L1UserTx []RollupEventL1UserTx
  178. AddToken []RollupEventAddToken
  179. ForgeBatch []RollupEventForgeBatch
  180. UpdateForgeL1L2BatchTimeout []RollupEventUpdateForgeL1L2BatchTimeout
  181. UpdateFeeAddToken []RollupEventUpdateFeeAddToken
  182. WithdrawEvent []RollupEventWithdrawEvent
  183. }
  184. // NewRollupEvents creates an empty RollupEvents with the slices initialized.
  185. func NewRollupEvents() RollupEvents {
  186. return RollupEvents{
  187. L1UserTx: make([]RollupEventL1UserTx, 0),
  188. AddToken: make([]RollupEventAddToken, 0),
  189. ForgeBatch: make([]RollupEventForgeBatch, 0),
  190. UpdateForgeL1L2BatchTimeout: make([]RollupEventUpdateForgeL1L2BatchTimeout, 0),
  191. UpdateFeeAddToken: make([]RollupEventUpdateFeeAddToken, 0),
  192. WithdrawEvent: make([]RollupEventWithdrawEvent, 0),
  193. }
  194. }
  195. // RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
  196. type RollupForgeBatchArgs struct {
  197. NewLastIdx int64
  198. NewStRoot *big.Int
  199. NewExitRoot *big.Int
  200. L1CoordinatorTxs []common.L1Tx
  201. L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx
  202. L2TxsData []common.L2Tx
  203. FeeIdxCoordinator []common.Idx
  204. // Circuit selector
  205. VerifierIdx uint8
  206. L1Batch bool
  207. ProofA [2]*big.Int
  208. ProofB [2][2]*big.Int
  209. ProofC [2]*big.Int
  210. }
  211. // RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract
  212. type RollupForgeBatchArgsAux struct {
  213. NewLastIdx *big.Int
  214. NewStRoot *big.Int
  215. NewExitRoot *big.Int
  216. EncodedL1CoordinatorTx []byte
  217. L2TxsData []byte
  218. FeeIdxCoordinator []byte
  219. // Circuit selector
  220. VerifierIdx uint8
  221. L1Batch bool
  222. ProofA [2]*big.Int
  223. ProofB [2][2]*big.Int
  224. ProofC [2]*big.Int
  225. }
  226. // RollupInterface is the inteface to to Rollup Smart Contract
  227. type RollupInterface interface {
  228. //
  229. // Smart Contract Methods
  230. //
  231. // Public Functions
  232. RollupForgeBatch(*RollupForgeBatchArgs) (*types.Transaction, error)
  233. RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error)
  234. RollupWithdrawMerkleProof(babyPubKey *babyjub.PublicKey, tokenID uint32, numExitRoot, idx int64, amount *big.Int, siblings []*big.Int, instantWithdraw bool) (*types.Transaction, error)
  235. RollupWithdrawCircuit(proofA, proofC [2]*big.Int, proofB [2][2]*big.Int, tokenID uint32, numExitRoot, idx int64, amount *big.Int, instantWithdraw bool) (*types.Transaction, error)
  236. RollupL1UserTxERC20ETH(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error)
  237. RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (*types.Transaction, error)
  238. // Governance Public Functions
  239. RollupUpdateForgeL1L2BatchTimeout(newForgeL1L2BatchTimeout int64) (*types.Transaction, error)
  240. RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error)
  241. // Viewers
  242. RollupRegisterTokensCount() (*big.Int, error)
  243. //
  244. // Smart Contract Status
  245. //
  246. RollupConstants() (*RollupPublicConstants, error)
  247. RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error)
  248. RollupForgeBatchArgs(ethCommon.Hash) (*RollupForgeBatchArgs, *ethCommon.Address, error)
  249. }
  250. //
  251. // Implementation
  252. //
  253. // RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum.
  254. type RollupClient struct {
  255. client *EthereumClient
  256. address ethCommon.Address
  257. tokenHEZAddress ethCommon.Address
  258. hermez *Hermez.Hermez
  259. contractAbi abi.ABI
  260. }
  261. // NewRollupClient creates a new RollupClient
  262. func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenHEZAddress ethCommon.Address) (*RollupClient, error) {
  263. contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI)))
  264. if err != nil {
  265. return nil, err
  266. }
  267. hermez, err := Hermez.NewHermez(address, client.Client())
  268. if err != nil {
  269. return nil, err
  270. }
  271. return &RollupClient{
  272. client: client,
  273. address: address,
  274. tokenHEZAddress: tokenHEZAddress,
  275. hermez: hermez,
  276. contractAbi: contractAbi,
  277. }, nil
  278. }
  279. // RollupForgeBatch is the interface to call the smart contract function
  280. func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (tx *types.Transaction, err error) {
  281. if tx, err = c.client.CallAuth(
  282. 1000000, //nolint:gomnd
  283. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  284. rollupConst, err := c.RollupConstants()
  285. if err != nil {
  286. return nil, err
  287. }
  288. nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels
  289. lenBytes := nLevels / 8 //nolint:gomnd
  290. newLastIdx := big.NewInt(int64(args.NewLastIdx))
  291. var l1CoordinatorBytes []byte
  292. for i := 0; i < len(args.L1CoordinatorTxs); i++ {
  293. l1 := args.L1CoordinatorTxs[i]
  294. bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i])
  295. if err != nil {
  296. return nil, err
  297. }
  298. l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...)
  299. }
  300. var l2DataBytes []byte
  301. for i := 0; i < len(args.L2TxsData); i++ {
  302. l2 := args.L2TxsData[i]
  303. bytesl2, err := l2.Bytes(int(nLevels))
  304. if err != nil {
  305. return nil, err
  306. }
  307. l2DataBytes = append(l2DataBytes, bytesl2[:]...)
  308. }
  309. var feeIdxCoordinator []byte
  310. if len(args.FeeIdxCoordinator) > RollupConstMaxFeeIdxCoordinator {
  311. return nil, fmt.Errorf("len(args.FeeIdxCoordinator) > %v",
  312. RollupConstMaxFeeIdxCoordinator)
  313. }
  314. for i := 0; i < RollupConstMaxFeeIdxCoordinator; i++ {
  315. feeIdx := common.Idx(0)
  316. if i < len(args.FeeIdxCoordinator) {
  317. feeIdx = args.FeeIdxCoordinator[i]
  318. }
  319. bytesFeeIdx, err := feeIdx.Bytes()
  320. if err != nil {
  321. return nil, err
  322. }
  323. feeIdxCoordinator = append(feeIdxCoordinator, bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...)
  324. }
  325. return c.hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot, l1CoordinatorBytes, l2DataBytes, feeIdxCoordinator, args.VerifierIdx, args.L1Batch, args.ProofA, args.ProofB, args.ProofC)
  326. },
  327. ); err != nil {
  328. return nil, fmt.Errorf("Failed forge batch: %w", err)
  329. }
  330. return tx, nil
  331. }
  332. // RollupAddToken is the interface to call the smart contract function.
  333. // `feeAddToken` is the amount of HEZ tokens that will be paid to add the
  334. // token. `feeAddToken` must match the public value of the smart contract.
  335. func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (tx *types.Transaction, err error) {
  336. if tx, err = c.client.CallAuth(
  337. 0,
  338. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  339. tokens, err := ERC777.NewERC777(c.tokenHEZAddress, ec)
  340. if err != nil {
  341. return nil, err
  342. }
  343. addTokenFnSignature := []byte("addToken(address)")
  344. hash := sha3.NewLegacyKeccak256()
  345. _, err = hash.Write(addTokenFnSignature)
  346. if err != nil {
  347. return nil, err
  348. }
  349. methodID := hash.Sum(nil)[:4]
  350. var data []byte
  351. data = append(data, methodID...)
  352. paddedAddress := ethCommon.LeftPadBytes(tokenAddress.Bytes(), 32)
  353. data = append(data, paddedAddress[:]...)
  354. return tokens.Send(auth, c.address, feeAddToken, data)
  355. },
  356. ); err != nil {
  357. return nil, fmt.Errorf("Failed add Token %w", err)
  358. }
  359. return tx, nil
  360. }
  361. // RollupWithdrawMerkleProof is the interface to call the smart contract function
  362. 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) {
  363. if tx, err = c.client.CallAuth(
  364. 0,
  365. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  366. hermez, err := Hermez.NewHermez(c.address, ec)
  367. if err != nil {
  368. return nil, err
  369. }
  370. pkCompL := fromBJJ.Compress()
  371. pkCompB := common.SwapEndianness(pkCompL[:])
  372. babyPubKey := new(big.Int).SetBytes(pkCompB)
  373. numExitRootB := big.NewInt(numExitRoot)
  374. idxBig := big.NewInt(idx)
  375. return hermez.WithdrawMerkleProof(auth, tokenID, amount, babyPubKey, numExitRootB, siblings, idxBig, instantWithdraw)
  376. },
  377. ); err != nil {
  378. return nil, fmt.Errorf("Failed update WithdrawMerkleProof: %w", err)
  379. }
  380. return tx, nil
  381. }
  382. // RollupWithdrawCircuit is the interface to call the smart contract function
  383. 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) {
  384. log.Error("TODO")
  385. return nil, errTODO
  386. }
  387. // RollupL1UserTxERC20ETH is the interface to call the smart contract function
  388. func (c *RollupClient) RollupL1UserTxERC20ETH(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (tx *types.Transaction, err error) {
  389. if tx, err = c.client.CallAuth(
  390. 0,
  391. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  392. hermez, err := Hermez.NewHermez(c.address, ec)
  393. if err != nil {
  394. return nil, err
  395. }
  396. pkCompL := fromBJJ.Compress()
  397. pkCompB := common.SwapEndianness(pkCompL[:])
  398. babyPubKey := new(big.Int).SetBytes(pkCompB)
  399. fromIdxBig := big.NewInt(fromIdx)
  400. toIdxBig := big.NewInt(toIdx)
  401. tokenIDBig := uint32(tokenID)
  402. loadAmountF, err := common.NewFloat16(loadAmount)
  403. if err != nil {
  404. return nil, err
  405. }
  406. amountF, err := common.NewFloat16(amount)
  407. if err != nil {
  408. return nil, err
  409. }
  410. if tokenID == 0 {
  411. auth.Value = loadAmount
  412. }
  413. return hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig, uint16(loadAmountF), uint16(amountF), tokenIDBig, toIdxBig)
  414. },
  415. ); err != nil {
  416. return nil, fmt.Errorf("Failed add L1 Tx ERC20/ETH: %w", err)
  417. }
  418. return tx, nil
  419. }
  420. // RollupL1UserTxERC777 is the interface to call the smart contract function
  421. func (c *RollupClient) RollupL1UserTxERC777(fromBJJ *babyjub.PublicKey, fromIdx int64, loadAmount *big.Int, amount *big.Int, tokenID uint32, toIdx int64) (tx *types.Transaction, err error) {
  422. if tx, err = c.client.CallAuth(
  423. 0,
  424. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  425. tokens, err := ERC777.NewERC777(c.tokenHEZAddress, ec)
  426. if err != nil {
  427. return nil, err
  428. }
  429. addL1TxFnSignature := []byte("addL1Transaction(uint256,uint48,uint16,uint16,uint32,uint48)")
  430. hash := sha3.NewLegacyKeccak256()
  431. _, err = hash.Write(addL1TxFnSignature)
  432. if err != nil {
  433. return nil, err
  434. }
  435. methodID := hash.Sum(nil)[:4]
  436. pkCompL := fromBJJ.Compress()
  437. pkCompB := common.SwapEndianness(pkCompL[:])
  438. paddedAddress := ethCommon.LeftPadBytes(pkCompB, 32)
  439. fromIdxB, err := common.Idx(fromIdx).Bytes()
  440. if err != nil {
  441. return nil, err
  442. }
  443. paddedFromIdx := ethCommon.LeftPadBytes(fromIdxB[:], 32)
  444. loadAmountF, err := common.NewFloat16(loadAmount)
  445. if err != nil {
  446. return nil, err
  447. }
  448. paddedLoadAmount := ethCommon.LeftPadBytes(loadAmountF.Bytes(), 32)
  449. amountF, err := common.NewFloat16(amount)
  450. if err != nil {
  451. return nil, err
  452. }
  453. paddedAmount := ethCommon.LeftPadBytes(amountF.Bytes(), 32)
  454. tokenIDB := common.TokenID(tokenID).Bytes()
  455. paddedTokenID := ethCommon.LeftPadBytes(tokenIDB, 32)
  456. toIdxB, err := common.Idx(toIdx).Bytes()
  457. if err != nil {
  458. return nil, err
  459. }
  460. paddedToIdx := ethCommon.LeftPadBytes(toIdxB[:], 32)
  461. var data []byte
  462. data = append(data, methodID...)
  463. data = append(data, paddedAddress[:]...)
  464. data = append(data, paddedFromIdx[:]...)
  465. data = append(data, paddedLoadAmount[:]...)
  466. data = append(data, paddedAmount[:]...)
  467. data = append(data, paddedTokenID[:]...)
  468. data = append(data, paddedToIdx[:]...)
  469. return tokens.Send(auth, c.address, loadAmount, data)
  470. },
  471. ); err != nil {
  472. return nil, fmt.Errorf("Failed add L1 Tx ERC777: %w", err)
  473. }
  474. return tx, nil
  475. }
  476. // RollupRegisterTokensCount is the interface to call the smart contract function
  477. func (c *RollupClient) RollupRegisterTokensCount() (*big.Int, error) {
  478. var registerTokensCount *big.Int
  479. if err := c.client.Call(func(ec *ethclient.Client) error {
  480. hermez, err := Hermez.NewHermez(c.address, ec)
  481. if err != nil {
  482. return err
  483. }
  484. registerTokensCount, err = hermez.RegisterTokensCount(nil)
  485. return err
  486. }); err != nil {
  487. return nil, err
  488. }
  489. return registerTokensCount, nil
  490. }
  491. // RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
  492. func (c *RollupClient) RollupUpdateForgeL1L2BatchTimeout(newForgeL1L2BatchTimeout int64) (tx *types.Transaction, err error) {
  493. if tx, err = c.client.CallAuth(
  494. 0,
  495. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  496. hermez, err := Hermez.NewHermez(c.address, ec)
  497. if err != nil {
  498. return nil, err
  499. }
  500. return hermez.UpdateForgeL1L2BatchTimeout(auth, uint8(newForgeL1L2BatchTimeout))
  501. },
  502. ); err != nil {
  503. return nil, fmt.Errorf("Failed update ForgeL1L2BatchTimeout: %w", err)
  504. }
  505. return tx, nil
  506. }
  507. // RollupUpdateFeeAddToken is the interface to call the smart contract function
  508. func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *types.Transaction, err error) {
  509. if tx, err = c.client.CallAuth(
  510. 0,
  511. func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
  512. hermez, err := Hermez.NewHermez(c.address, ec)
  513. if err != nil {
  514. return nil, err
  515. }
  516. return hermez.UpdateFeeAddToken(auth, newFeeAddToken)
  517. },
  518. ); err != nil {
  519. return nil, fmt.Errorf("Failed update FeeAddToken: %w", err)
  520. }
  521. return tx, nil
  522. }
  523. // RollupConstants returns the Constants of the Rollup Smart Contract
  524. func (c *RollupClient) RollupConstants() (rollupConstants *RollupPublicConstants, err error) {
  525. rollupConstants = new(RollupPublicConstants)
  526. if err := c.client.Call(func(ec *ethclient.Client) error {
  527. absoluteMaxL1L2BatchTimeout, err := c.hermez.ABSOLUTEMAXL1L2BATCHTIMEOUT(nil)
  528. if err != nil {
  529. return err
  530. }
  531. rollupConstants.AbsoluteMaxL1L2BatchTimeout = int64(absoluteMaxL1L2BatchTimeout)
  532. rollupConstants.TokenHEZ, err = c.hermez.TokenHEZ(nil)
  533. if err != nil {
  534. return err
  535. }
  536. for i := int64(0); i < int64(LenVerifiers); i++ {
  537. var newRollupVerifier RollupVerifierStruct
  538. rollupVerifier, err := c.hermez.RollupVerifiers(nil, big.NewInt(i))
  539. if err != nil {
  540. return err
  541. }
  542. newRollupVerifier.MaxTx = rollupVerifier.MaxTx.Int64()
  543. newRollupVerifier.NLevels = rollupVerifier.NLevels.Int64()
  544. rollupConstants.Verifiers = append(rollupConstants.Verifiers, newRollupVerifier)
  545. }
  546. rollupConstants.HermezAuctionContract, err = c.hermez.HermezAuctionContract(nil)
  547. if err != nil {
  548. return err
  549. }
  550. rollupConstants.HermezGovernanceDAOAddress, err = c.hermez.HermezGovernanceDAOAddress(nil)
  551. if err != nil {
  552. return err
  553. }
  554. rollupConstants.SafetyAddress, err = c.hermez.SafetyAddress(nil)
  555. if err != nil {
  556. return err
  557. }
  558. rollupConstants.WithdrawDelayerContract, err = c.hermez.WithdrawDelayerContract(nil)
  559. return err
  560. }); err != nil {
  561. return nil, err
  562. }
  563. return rollupConstants, nil
  564. }
  565. var (
  566. logHermezL1UserTxEvent = crypto.Keccak256Hash([]byte("L1UserTxEvent(uint64,uint8,bytes)"))
  567. logHermezAddToken = crypto.Keccak256Hash([]byte("AddToken(address,uint32)"))
  568. logHermezForgeBatch = crypto.Keccak256Hash([]byte("ForgeBatch(uint64)"))
  569. logHermezUpdateForgeL1L2BatchTimeout = crypto.Keccak256Hash([]byte("UpdateForgeL1L2BatchTimeout(uint8)"))
  570. logHermezUpdateFeeAddToken = crypto.Keccak256Hash([]byte("UpdateFeeAddToken(uint256)"))
  571. logHermezWithdrawEvent = crypto.Keccak256Hash([]byte("WithdrawEvent(uint48,uint48,bool)"))
  572. )
  573. // RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
  574. func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error) {
  575. var rollupEvents RollupEvents
  576. var blockHash ethCommon.Hash
  577. query := ethereum.FilterQuery{
  578. FromBlock: big.NewInt(blockNum),
  579. ToBlock: big.NewInt(blockNum),
  580. Addresses: []ethCommon.Address{
  581. c.address,
  582. },
  583. BlockHash: nil,
  584. Topics: [][]ethCommon.Hash{},
  585. }
  586. logs, err := c.client.client.FilterLogs(context.Background(), query)
  587. if err != nil {
  588. return nil, nil, err
  589. }
  590. if len(logs) > 0 {
  591. blockHash = logs[0].BlockHash
  592. }
  593. for _, vLog := range logs {
  594. if vLog.BlockHash != blockHash {
  595. return nil, nil, ErrBlockHashMismatchEvent
  596. }
  597. switch vLog.Topics[0] {
  598. case logHermezL1UserTxEvent:
  599. var L1UserTxAux RollupEventL1UserTxAux
  600. var L1UserTx RollupEventL1UserTx
  601. err := c.contractAbi.Unpack(&L1UserTxAux, "L1UserTxEvent", vLog.Data)
  602. if err != nil {
  603. return nil, nil, err
  604. }
  605. L1Tx, err := common.L1UserTxFromBytes(L1UserTxAux.L1UserTx)
  606. if err != nil {
  607. return nil, nil, err
  608. }
  609. toForgeL1TxsNum := new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  610. L1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum
  611. L1Tx.Position = int(new(big.Int).SetBytes(vLog.Topics[2][:]).Int64())
  612. L1Tx.UserOrigin = true
  613. L1UserTx.L1UserTx = *L1Tx
  614. rollupEvents.L1UserTx = append(rollupEvents.L1UserTx, L1UserTx)
  615. case logHermezAddToken:
  616. var addToken RollupEventAddToken
  617. err := c.contractAbi.Unpack(&addToken, "AddToken", vLog.Data)
  618. if err != nil {
  619. return nil, nil, err
  620. }
  621. addToken.TokenAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
  622. rollupEvents.AddToken = append(rollupEvents.AddToken, addToken)
  623. case logHermezForgeBatch:
  624. var forgeBatch RollupEventForgeBatch
  625. forgeBatch.BatchNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
  626. forgeBatch.EthTxHash = vLog.TxHash
  627. // forgeBatch.Sender = vLog.Address
  628. rollupEvents.ForgeBatch = append(rollupEvents.ForgeBatch, forgeBatch)
  629. case logHermezUpdateForgeL1L2BatchTimeout:
  630. var updateForgeL1L2BatchTimeout struct {
  631. NewForgeL1L2BatchTimeout uint8
  632. }
  633. err := c.contractAbi.Unpack(&updateForgeL1L2BatchTimeout, "UpdateForgeL1L2BatchTimeout", vLog.Data)
  634. if err != nil {
  635. return nil, nil, err
  636. }
  637. rollupEvents.UpdateForgeL1L2BatchTimeout = append(rollupEvents.UpdateForgeL1L2BatchTimeout,
  638. RollupEventUpdateForgeL1L2BatchTimeout{
  639. NewForgeL1L2BatchTimeout: int64(updateForgeL1L2BatchTimeout.NewForgeL1L2BatchTimeout),
  640. })
  641. case logHermezUpdateFeeAddToken:
  642. var updateFeeAddToken RollupEventUpdateFeeAddToken
  643. err := c.contractAbi.Unpack(&updateFeeAddToken, "UpdateFeeAddToken", vLog.Data)
  644. if err != nil {
  645. return nil, nil, err
  646. }
  647. rollupEvents.UpdateFeeAddToken = append(rollupEvents.UpdateFeeAddToken, updateFeeAddToken)
  648. case logHermezWithdrawEvent:
  649. var withdraw RollupEventWithdrawEvent
  650. withdraw.Idx = new(big.Int).SetBytes(vLog.Topics[1][:]).Uint64()
  651. withdraw.NumExitRoot = new(big.Int).SetBytes(vLog.Topics[2][:]).Uint64()
  652. instantWithdraw := new(big.Int).SetBytes(vLog.Topics[3][:]).Uint64()
  653. if instantWithdraw == 1 {
  654. withdraw.InstantWithdraw = true
  655. }
  656. rollupEvents.WithdrawEvent = append(rollupEvents.WithdrawEvent, withdraw)
  657. }
  658. }
  659. return &rollupEvents, &blockHash, nil
  660. }
  661. // RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the
  662. // Rollup Smart Contract in the given transaction, and the sender address.
  663. func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupForgeBatchArgs, *ethCommon.Address, error) {
  664. tx, _, err := c.client.client.TransactionByHash(context.Background(), ethTxHash)
  665. if err != nil {
  666. return nil, nil, err
  667. }
  668. txData := tx.Data()
  669. method, err := c.contractAbi.MethodById(txData[:4])
  670. if err != nil {
  671. return nil, nil, err
  672. }
  673. receipt, err := c.client.client.TransactionReceipt(context.Background(), ethTxHash)
  674. if err != nil {
  675. return nil, nil, err
  676. }
  677. sender, err := c.client.client.TransactionSender(context.Background(), tx, receipt.Logs[0].BlockHash, receipt.Logs[0].Index)
  678. if err != nil {
  679. return nil, nil, err
  680. }
  681. var aux RollupForgeBatchArgsAux
  682. if err := method.Inputs.Unpack(&aux, txData[4:]); err != nil {
  683. return nil, nil, err
  684. }
  685. rollupForgeBatchArgs := RollupForgeBatchArgs{
  686. L1Batch: aux.L1Batch,
  687. NewExitRoot: aux.NewExitRoot,
  688. NewLastIdx: aux.NewLastIdx.Int64(),
  689. NewStRoot: aux.NewStRoot,
  690. ProofA: aux.ProofA,
  691. ProofB: aux.ProofB,
  692. ProofC: aux.ProofC,
  693. VerifierIdx: aux.VerifierIdx,
  694. L1CoordinatorTxs: []common.L1Tx{},
  695. L1CoordinatorTxsAuths: [][]byte{},
  696. L2TxsData: []common.L2Tx{},
  697. FeeIdxCoordinator: []common.Idx{},
  698. }
  699. numTxsL1 := len(aux.EncodedL1CoordinatorTx) / common.L1CoordinatorTxBytesLen
  700. for i := 0; i < numTxsL1; i++ {
  701. bytesL1Coordinator := aux.EncodedL1CoordinatorTx[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen]
  702. var signature []byte
  703. v := bytesL1Coordinator[0]
  704. s := bytesL1Coordinator[1:33]
  705. r := bytesL1Coordinator[33:65]
  706. signature = append(signature, r[:]...)
  707. signature = append(signature, s[:]...)
  708. signature = append(signature, v)
  709. l1Tx, err := common.L1CoordinatorTxFromBytes(bytesL1Coordinator)
  710. if err != nil {
  711. return nil, nil, err
  712. }
  713. rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, *l1Tx)
  714. rollupForgeBatchArgs.L1CoordinatorTxsAuths = append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature)
  715. }
  716. rollupConsts, err := c.RollupConstants()
  717. if err != nil {
  718. return nil, nil, err
  719. }
  720. nLevels := rollupConsts.Verifiers[rollupForgeBatchArgs.VerifierIdx].NLevels
  721. lenL2TxsBytes := int((nLevels/8)*2 + 2 + 1)
  722. numTxsL2 := len(aux.L2TxsData) / lenL2TxsBytes
  723. for i := 0; i < numTxsL2; i++ {
  724. l2Tx, err := common.L2TxFromBytes(aux.L2TxsData[i*lenL2TxsBytes:(i+1)*lenL2TxsBytes], int(nLevels))
  725. if err != nil {
  726. return nil, nil, err
  727. }
  728. rollupForgeBatchArgs.L2TxsData = append(rollupForgeBatchArgs.L2TxsData, *l2Tx)
  729. }
  730. lenFeeIdxCoordinatorBytes := int(nLevels / 8) //nolint:gomnd
  731. numFeeIdxCoordinator := len(aux.FeeIdxCoordinator) / lenFeeIdxCoordinatorBytes
  732. for i := 0; i < numFeeIdxCoordinator; i++ {
  733. var paddedFeeIdx [6]byte
  734. // TODO: This check is not necessary: the first case will always work. Test it before removing the if.
  735. if lenFeeIdxCoordinatorBytes < common.IdxBytesLen {
  736. copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
  737. } else {
  738. copy(paddedFeeIdx[:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
  739. }
  740. feeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:])
  741. if err != nil {
  742. return nil, nil, err
  743. }
  744. if feeIdxCoordinator != common.Idx(0) {
  745. rollupForgeBatchArgs.FeeIdxCoordinator = append(rollupForgeBatchArgs.FeeIdxCoordinator, feeIdxCoordinator)
  746. }
  747. }
  748. return &rollupForgeBatchArgs, &sender, nil
  749. }