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