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.

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