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
153//nolint:structcheck
154type QueueStruct struct {
155 L1TxQueue []common.L1Tx
156 TotalL1TxFee *big.Int
157}
158
159// NewQueueStruct creates a new clear QueueStruct.
160func NewQueueStruct() *QueueStruct {
161 return &QueueStruct{
162 L1TxQueue: make([]common.L1Tx, 0),
163 TotalL1TxFee: big.NewInt(0),
164 }
165}
166
167// RollupVerifierStruct is the information about verifiers of the Rollup Smart Contract
168type RollupVerifierStruct struct {
169 MaxTx int64
170 NLevels int64
171}
172
173// RollupState represents the state of the Rollup in the Smart Contract
174//nolint:structcheck,unused
175type RollupState struct {
176 StateRoot *big.Int
177 ExitRoots []*big.Int
178 ExitNullifierMap map[[256 / 8]byte]bool
179 TokenList []ethCommon.Address
180 TokenMap map[ethCommon.Address]bool
181 MapL1TxQueue map[int64]*QueueStruct
182 LastL1L2Batch int64
183 CurrentToForgeL1TxsNum int64
184 LastToForgeL1TxsNum int64
185 CurrentIdx int64
186}
187
188// RollupEventL1UserTx is an event of the Rollup Smart Contract
189type RollupEventL1UserTx struct {
190 ToForgeL1TxsNum int64 // QueueIndex *big.Int
191 Position int // TransactionIndex *big.Int
192 L1Tx common.L1Tx
193}
194
195// RollupEventL1UserTxAux is an event of the Rollup Smart Contract
196type RollupEventL1UserTxAux struct {
197 ToForgeL1TxsNum uint64 // QueueIndex *big.Int
198 Position uint8 // TransactionIndex *big.Int
199 L1Tx []byte
200}
201
202// RollupEventAddToken is an event of the Rollup Smart Contract
203type RollupEventAddToken struct {
204 Address ethCommon.Address
205 TokenID uint32
206}
207
208// RollupEventForgeBatch is an event of the Rollup Smart Contract
209type RollupEventForgeBatch struct {
210 BatchNum int64
211 EthTxHash ethCommon.Hash
212}
213
214// RollupEventUpdateForgeL1L2BatchTimeout is an event of the Rollup Smart Contract
215type RollupEventUpdateForgeL1L2BatchTimeout struct {
216 ForgeL1L2BatchTimeout uint8
217}
218
219// RollupEventUpdateFeeAddToken is an event of the Rollup Smart Contract
220type RollupEventUpdateFeeAddToken struct {
221 FeeAddToken *big.Int
222}
223
224// RollupEventWithdrawEvent is an event of the Rollup Smart Contract
225type RollupEventWithdrawEvent struct {
226 Idx uint64
227 NumExitRoot uint64
228 InstantWithdraw bool
229}
230
231// RollupEvents is the list of events in a block of the Rollup Smart Contract
232type RollupEvents struct { //nolint:structcheck
233 L1UserTx []RollupEventL1UserTx
234 AddToken []RollupEventAddToken
235 ForgeBatch []RollupEventForgeBatch
236 UpdateForgeL1L2BatchTimeout []RollupEventUpdateForgeL1L2BatchTimeout
237 UpdateFeeAddToken []RollupEventUpdateFeeAddToken
238 WithdrawEvent []RollupEventWithdrawEvent
239}
240
241// NewRollupEvents creates an empty RollupEvents with the slices initialized.
242func NewRollupEvents() RollupEvents {
243 return RollupEvents{
244 L1UserTx: make([]RollupEventL1UserTx, 0),
245 AddToken: make([]RollupEventAddToken, 0),
246 ForgeBatch: make([]RollupEventForgeBatch, 0),
247 UpdateForgeL1L2BatchTimeout: make([]RollupEventUpdateForgeL1L2BatchTimeout, 0),
248 UpdateFeeAddToken: make([]RollupEventUpdateFeeAddToken, 0),
249 WithdrawEvent: make([]RollupEventWithdrawEvent, 0),
250 }
251}
252
253// RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
254//nolint:structcheck,unused
255type RollupForgeBatchArgs struct {
256 NewLastIdx int64
257 NewStRoot *big.Int
258 NewExitRoot *big.Int
259 L1CoordinatorTxs []*common.L1Tx
260 L1CoordinatorTxsAuths [][]byte // Authorization for accountCreations for each L1CoordinatorTx
261 L2TxsData []*common.L2Tx
262 FeeIdxCoordinator []common.Idx
263 // Circuit selector
264 VerifierIdx uint8
265 L1Batch bool
266 ProofA [2]*big.Int
267 ProofB [2][2]*big.Int
268 ProofC [2]*big.Int
269}
270
271// RollupForgeBatchArgsAux are the arguments to the ForgeBatch function in the Rollup Smart Contract
272//nolint:structcheck,unused
273type RollupForgeBatchArgsAux struct {
274 NewLastIdx *big.Int
275 NewStRoot *big.Int
276 NewExitRoot *big.Int
277 EncodedL1CoordinatorTx []byte
278 L2TxsData []byte
279 FeeIdxCoordinator []byte
280 // Circuit selector
281 VerifierIdx uint8
282 L1Batch bool
283 ProofA [2]*big.Int
284 ProofB [2][2]*big.Int
285 ProofC [2]*big.Int
286}
287
288// RollupInterface is the inteface to to Rollup Smart Contract
289type RollupInterface interface {
290 //
291 // Smart Contract Methods
292 //
293
294 // Public Functions
295
296 RollupForgeBatch(*RollupForgeBatchArgs) (*types.Transaction, error)
297 RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error)
298 RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey,
299 numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error)
300 RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error)
301 RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error)
302 RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey,
303 loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error)
304 RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16,
305 tokenID int64, toIdx int64) (*types.Transaction, error)
306 RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error)
307 RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte,
308 babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error)
309 RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16,
310 tokenID int64) (*types.Transaction, error)
311
312 RollupGetCurrentTokens() (*big.Int, error)
313 // RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error)
314 // RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error)
315 // RollupGetQueue(queue int64) ([]byte, error)
316
317 // Governance Public Functions
318 RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (*types.Transaction, error)
319 RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error)
320
321 //
322 // Smart Contract Status
323 //
324
325 RollupConstants() (*RollupPublicConstants, error)
326 RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error)
327 RollupForgeBatchArgs(ethCommon.Hash) (*RollupForgeBatchArgs, error)
328}
329
330//
331// Implementation
332//
333
334// RollupClient is the implementation of the interface to the Rollup Smart Contract in ethereum.
335type RollupClient struct {
336 client *EthereumClient
337 address ethCommon.Address
338 tokenHEZAddress ethCommon.Address
339 gasLimit uint64
340 contractAbi abi.ABI
341}
342
343// NewRollupClient creates a new RollupClient
344func NewRollupClient(client *EthereumClient, address ethCommon.Address, tokenHEZAddress ethCommon.Address) (*RollupClient, error) {
345 contractAbi, err := abi.JSON(strings.NewReader(string(Hermez.HermezABI)))
346 if err != nil {
347 return nil, err
348 }
349 return &RollupClient{
350 client: client,
351 address: address,
352 tokenHEZAddress: tokenHEZAddress,
353 gasLimit: 1000000, //nolint:gomnd
354 contractAbi: contractAbi,
355 }, nil
356}
357
358// RollupForgeBatch is the interface to call the smart contract function
359func (c *RollupClient) RollupForgeBatch(args *RollupForgeBatchArgs) (*types.Transaction, error) {
360 var tx *types.Transaction
361 var err error
362 if tx, err = c.client.CallAuth(
363 c.gasLimit,
364 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
365 hermez, err := Hermez.NewHermez(c.address, ec)
366 if err != nil {
367 return nil, err
368 }
369 rollupConst, err := c.RollupConstants()
370 if err != nil {
371 return nil, err
372 }
373 nLevels := rollupConst.Verifiers[args.VerifierIdx].NLevels
374 lenBytes := nLevels / 8 //nolint:gomnd
375 newLastIdx := big.NewInt(int64(args.NewLastIdx))
376 var l1CoordinatorBytes []byte
377 for i := 0; i < len(args.L1CoordinatorTxs); i++ {
378 l1 := args.L1CoordinatorTxs[i]
379 bytesl1, err := l1.BytesCoordinatorTx(args.L1CoordinatorTxsAuths[i])
380 if err != nil {
381 return nil, err
382 }
383 l1CoordinatorBytes = append(l1CoordinatorBytes, bytesl1[:]...)
384 }
385 var l2DataBytes []byte
386 for i := 0; i < len(args.L2TxsData); i++ {
387 l2 := args.L2TxsData[i]
388 bytesl2, err := l2.Bytes(int(nLevels))
389 if err != nil {
390 return nil, err
391 }
392 l2DataBytes = append(l2DataBytes, bytesl2[:]...)
393 }
394 var feeIdxCoordinator []byte
395 for i := 0; i < len(args.FeeIdxCoordinator); i++ {
396 feeIdx := args.FeeIdxCoordinator[i]
397 bytesFeeIdx, err := feeIdx.Bytes()
398 if err != nil {
399 return nil, err
400 }
401 feeIdxCoordinator = append(feeIdxCoordinator, bytesFeeIdx[len(bytesFeeIdx)-int(lenBytes):]...)
402 }
403 return hermez.ForgeBatch(auth, newLastIdx, args.NewStRoot, args.NewExitRoot, l1CoordinatorBytes, l2DataBytes, feeIdxCoordinator, args.VerifierIdx, args.L1Batch, args.ProofA, args.ProofB, args.ProofC)
404 },
405 ); err != nil {
406 return nil, fmt.Errorf("Failed forge batch: %w", err)
407 }
408 return tx, nil
409}
410
411// RollupAddToken is the interface to call the smart contract function.
412// `feeAddToken` is the amount of HEZ tokens that will be paid to add the
413// token. `feeAddToken` must match the public value of the smart contract.
414func (c *RollupClient) RollupAddToken(tokenAddress ethCommon.Address, feeAddToken *big.Int) (*types.Transaction, error) {
415 var tx *types.Transaction
416 var err error
417 if tx, err = c.client.CallAuth(
418 c.gasLimit,
419 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
420 tokens, err := ERC777.NewERC777(c.tokenHEZAddress, ec)
421 if err != nil {
422 return nil, err
423 }
424 addTokenFnSignature := []byte("addToken(address)")
425 hash := sha3.NewLegacyKeccak256()
426 _, err = hash.Write(addTokenFnSignature)
427 if err != nil {
428 return nil, err
429 }
430 methodID := hash.Sum(nil)[:4]
431 var data []byte
432 data = append(data, methodID...)
433 paddedAddress := ethCommon.LeftPadBytes(tokenAddress.Bytes(), 32)
434 data = append(data, paddedAddress[:]...)
435 return tokens.Send(auth, c.address, feeAddToken, data)
436 },
437 ); err != nil {
438 return nil, fmt.Errorf("Failed add Token %w", err)
439 }
440 return tx, nil
441}
442
443// RollupWithdrawSNARK is the interface to call the smart contract function
444// func (c *RollupClient) RollupWithdrawSNARK() (*types.Transaction, error) { // TODO (Not defined in Hermez.sol)
445// return nil, errTODO
446// }
447
448// RollupWithdraw is the interface to call the smart contract function
449func (c *RollupClient) RollupWithdraw(tokenID int64, balance *big.Int, babyPubKey *babyjub.PublicKey, numExitRoot int64, siblings []*big.Int, idx int64, instantWithdraw bool) (*types.Transaction, error) {
450 log.Error("TODO")
451 return nil, errTODO
452}
453
454// RollupForceExit is the interface to call the smart contract function
455func (c *RollupClient) RollupForceExit(fromIdx int64, amountF common.Float16, tokenID int64) (*types.Transaction, error) {
456 log.Error("TODO")
457 return nil, errTODO
458}
459
460// RollupForceTransfer is the interface to call the smart contract function
461func (c *RollupClient) RollupForceTransfer(fromIdx int64, amountF common.Float16, tokenID, toIdx int64) (*types.Transaction, error) {
462 log.Error("TODO")
463 return nil, errTODO
464}
465
466// RollupCreateAccountDepositTransfer is the interface to call the smart contract function
467func (c *RollupClient) RollupCreateAccountDepositTransfer(babyPubKey babyjub.PublicKey, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
468 log.Error("TODO")
469 return nil, errTODO
470}
471
472// RollupDepositTransfer is the interface to call the smart contract function
473func (c *RollupClient) RollupDepositTransfer(fromIdx int64, loadAmountF, amountF common.Float16, tokenID int64, toIdx int64) (*types.Transaction, error) {
474 log.Error("TODO")
475 return nil, errTODO
476}
477
478// RollupDeposit is the interface to call the smart contract function
479func (c *RollupClient) RollupDeposit(fromIdx int64, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
480 log.Error("TODO")
481 return nil, errTODO
482}
483
484// RollupCreateAccountDepositFromRelayer is the interface to call the smart contract function
485func (c *RollupClient) RollupCreateAccountDepositFromRelayer(accountCreationAuthSig []byte, babyPubKey babyjub.PublicKey, loadAmountF common.Float16) (*types.Transaction, error) {
486 log.Error("TODO")
487 return nil, errTODO
488}
489
490// RollupCreateAccountDeposit is the interface to call the smart contract function
491func (c *RollupClient) RollupCreateAccountDeposit(babyPubKey babyjub.PublicKey, loadAmountF common.Float16, tokenID int64) (*types.Transaction, error) {
492 log.Error("TODO")
493 return nil, errTODO
494}
495
496// RollupGetTokenAddress is the interface to call the smart contract function
497/* func (c *RollupClient) RollupGetTokenAddress(tokenID int64) (*ethCommon.Address, error) {
498 return nil, errTODO
499} */
500
501// RollupGetCurrentTokens is the interface to call the smart contract function
502func (c *RollupClient) RollupGetCurrentTokens() (*big.Int, error) {
503 log.Error("TODO")
504 return nil, errTODO
505}
506
507// RollupGetL1TxFromQueue is the interface to call the smart contract function
508/* func (c *RollupClient) RollupGetL1TxFromQueue(queue int64, position int64) ([]byte, error) {
509 return nil, errTODO
510} */
511
512// RollupGetQueue is the interface to call the smart contract function
513/* func (c *RollupClient) RollupGetQueue(queue int64) ([]byte, error) {
514 return nil, errTODO
515}*/
516
517// RollupUpdateForgeL1L2BatchTimeout is the interface to call the smart contract function
518func (c *RollupClient) RollupUpdateForgeL1L2BatchTimeout(newForgeL1Timeout int64) (*types.Transaction, error) {
519 log.Error("TODO")
520 return nil, errTODO
521}
522
523// RollupUpdateFeeAddToken is the interface to call the smart contract function
524func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (*types.Transaction, error) {
525 log.Error("TODO")
526 return nil, errTODO
527}
528
529// RollupConstants returns the Constants of the Rollup Smart Contract
530func (c *RollupClient) RollupConstants() (*RollupPublicConstants, error) {
531 rollupConstants := new(RollupPublicConstants)
532 if err := c.client.Call(func(ec *ethclient.Client) error {
533 hermez, err := Hermez.NewHermez(c.address, ec)
534 if err != nil {
535 return err
536 }
537 absoluteMaxL1L2BatchTimeout, err := hermez.ABSOLUTEMAXL1L2BATCHTIMEOUT(nil)
538 if err != nil {
539 return err
540 }
541 rollupConstants.AbsoluteMaxL1L2BatchTimeout = int64(absoluteMaxL1L2BatchTimeout)
542 rollupConstants.TokenHEZ, err = hermez.TokenHEZ(nil)
543 if err != nil {
544 return err
545 }
546 for i := int64(0); i < int64(LenVerifiers); i++ {
547 var newRollupVerifier RollupVerifierStruct
548 rollupVerifier, err := hermez.RollupVerifiers(nil, big.NewInt(i))
549 if err != nil {
550 return err
551 }
552 newRollupVerifier.MaxTx = rollupVerifier.MaxTx.Int64()
553 newRollupVerifier.NLevels = rollupVerifier.NLevels.Int64()
554 rollupConstants.Verifiers = append(rollupConstants.Verifiers, newRollupVerifier)
555 }
556 rollupConstants.HermezAuctionContract, err = hermez.HermezAuctionContract(nil)
557 if err != nil {
558 return err
559 }
560 rollupConstants.HermezGovernanceDAOAddress, err = hermez.HermezGovernanceDAOAddress(nil)
561 if err != nil {
562 return err
563 }
564 rollupConstants.SafetyAddress, err = hermez.SafetyAddress(nil)
565 if err != nil {
566 return err
567 }
568 rollupConstants.WithdrawDelayerContract, err = hermez.WithdrawDelayerContract(nil)
569 return err
570 }); err != nil {
571 return nil, err
572 }
573 return rollupConstants, nil
574}
575
576var (
577 logHermezL1UserTxEvent = crypto.Keccak256Hash([]byte("L1UserTxEvent(uint64,uint8,bytes)"))
578 logHermezAddToken = crypto.Keccak256Hash([]byte("AddToken(address,uint32)"))
579 logHermezForgeBatch = crypto.Keccak256Hash([]byte("ForgeBatch(uint64)"))
580 logHermezUpdateForgeL1L2BatchTimeout = crypto.Keccak256Hash([]byte("UpdateForgeL1L2BatchTimeout(uint8)"))
581 logHermezUpdateFeeAddToken = crypto.Keccak256Hash([]byte("UpdateFeeAddToken(uint256)"))
582 logHermezWithdrawEvent = crypto.Keccak256Hash([]byte("WithdrawEvent(uint48,uint48,bool)"))
583)
584
585// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
586func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error) {
587 var rollupEvents RollupEvents
588 var blockHash ethCommon.Hash
589
590 query := ethereum.FilterQuery{
591 FromBlock: big.NewInt(blockNum),
592 ToBlock: big.NewInt(blockNum),
593 Addresses: []ethCommon.Address{
594 c.address,
595 },
596 BlockHash: nil,
597 Topics: [][]ethCommon.Hash{},
598 }
599 logs, err := c.client.client.FilterLogs(context.Background(), query)
600 if err != nil {
601 return nil, nil, err
602 }
603 if len(logs) > 0 {
604 blockHash = logs[0].BlockHash
605 }
606 for _, vLog := range logs {
607 if vLog.BlockHash != blockHash {
608 return nil, nil, ErrBlockHashMismatchEvent
609 }
610 switch vLog.Topics[0] {
611 case logHermezL1UserTxEvent:
612 var L1UserTxAux RollupEventL1UserTxAux
613 var L1UserTx RollupEventL1UserTx
614 err := c.contractAbi.Unpack(&L1UserTxAux, "L1UserTxEvent", vLog.Data)
615 if err != nil {
616 return nil, nil, err
617 }
618 L1Tx, err := common.L1TxFromBytes(L1UserTxAux.L1Tx)
619 if err != nil {
620 return nil, nil, err
621 }
622 L1UserTx.ToForgeL1TxsNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
623 L1UserTx.Position = int(new(big.Int).SetBytes(vLog.Topics[2][:]).Int64())
624 L1UserTx.L1Tx = *L1Tx
625 rollupEvents.L1UserTx = append(rollupEvents.L1UserTx, L1UserTx)
626 case logHermezAddToken:
627 var addToken RollupEventAddToken
628 err := c.contractAbi.Unpack(&addToken, "AddToken", vLog.Data)
629 if err != nil {
630 return nil, nil, err
631 }
632 addToken.Address = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
633 rollupEvents.AddToken = append(rollupEvents.AddToken, addToken)
634 case logHermezForgeBatch:
635 var forgeBatch RollupEventForgeBatch
636 forgeBatch.BatchNum = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
637 forgeBatch.EthTxHash = vLog.TxHash
638 rollupEvents.ForgeBatch = append(rollupEvents.ForgeBatch, forgeBatch)
639 case logHermezUpdateForgeL1L2BatchTimeout:
640 var updateForgeL1L2BatchTimeout RollupEventUpdateForgeL1L2BatchTimeout
641 err := c.contractAbi.Unpack(&updateForgeL1L2BatchTimeout, "UpdateForgeL1L2BatchTimeout", vLog.Data)
642 if err != nil {
643 return nil, nil, err
644 }
645 rollupEvents.UpdateForgeL1L2BatchTimeout = append(rollupEvents.UpdateForgeL1L2BatchTimeout, updateForgeL1L2BatchTimeout)
646 case logHermezUpdateFeeAddToken:
647 var updateFeeAddToken RollupEventUpdateFeeAddToken
648 err := c.contractAbi.Unpack(&updateFeeAddToken, "UpdateFeeAddToken", vLog.Data)
649 if err != nil {
650 return nil, nil, err
651 }
652 rollupEvents.UpdateFeeAddToken = append(rollupEvents.UpdateFeeAddToken, updateFeeAddToken)
653 case logHermezWithdrawEvent:
654 var withdraw RollupEventWithdrawEvent
655 err := c.contractAbi.Unpack(&withdraw, "WithdrawEvent", vLog.Data)
656 if err != nil {
657 return nil, nil, err
658 }
659 withdraw.Idx = new(big.Int).SetBytes(vLog.Topics[1][:]).Uint64()
660 withdraw.NumExitRoot = new(big.Int).SetBytes(vLog.Topics[2][:]).Uint64()
661 rollupEvents.WithdrawEvent = append(rollupEvents.WithdrawEvent, withdraw)
662 }
663 }
664 return &rollupEvents, &blockHash, nil
665}
666
667// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
668func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupForgeBatchArgs, error) {
669 tx, _, err := c.client.client.TransactionByHash(context.Background(), ethTxHash)
670 if err != nil {
671 return nil, err
672 }
673 txData := tx.Data()
674 method, err := c.contractAbi.MethodById(txData[:4])
675 if err != nil {
676 return nil, err
677 }
678 var aux RollupForgeBatchArgsAux
679 if err := method.Inputs.Unpack(&aux, txData[4:]); err != nil {
680 return nil, err
681 }
682 var rollupForgeBatchArgs RollupForgeBatchArgs
683 rollupForgeBatchArgs.L1Batch = aux.L1Batch
684 rollupForgeBatchArgs.NewExitRoot = aux.NewExitRoot
685 rollupForgeBatchArgs.NewLastIdx = aux.NewLastIdx.Int64()
686 rollupForgeBatchArgs.NewStRoot = aux.NewStRoot
687 rollupForgeBatchArgs.ProofA = aux.ProofA
688 rollupForgeBatchArgs.ProofB = aux.ProofB
689 rollupForgeBatchArgs.ProofC = aux.ProofC
690 rollupForgeBatchArgs.VerifierIdx = aux.VerifierIdx
691 numTxsL1 := len(aux.EncodedL1CoordinatorTx) / common.L1CoordinatorTxBytesLen
692 for i := 0; i < numTxsL1; i++ {
693 bytesL1Coordinator := aux.EncodedL1CoordinatorTx[i*common.L1CoordinatorTxBytesLen : (i+1)*common.L1CoordinatorTxBytesLen]
694 var signature []byte
695 v := bytesL1Coordinator[0]
696 s := bytesL1Coordinator[1:33]
697 r := bytesL1Coordinator[33:65]
698 signature = append(signature, r[:]...)
699 signature = append(signature, s[:]...)
700 signature = append(signature, v)
701 l1Tx, err := common.L1TxFromCoordinatorBytes(bytesL1Coordinator)
702 if err != nil {
703 return nil, err
704 }
705 rollupForgeBatchArgs.L1CoordinatorTxs = append(rollupForgeBatchArgs.L1CoordinatorTxs, l1Tx)
706 rollupForgeBatchArgs.L1CoordinatorTxsAuths = append(rollupForgeBatchArgs.L1CoordinatorTxsAuths, signature)
707 }
708 rollupConsts, err := c.RollupConstants()
709 if err != nil {
710 return nil, err
711 }
712 nLevels := rollupConsts.Verifiers[rollupForgeBatchArgs.VerifierIdx].NLevels
713 lenL2TxsBytes := int((nLevels/8)*2 + 2 + 1)
714 numTxsL2 := len(aux.L2TxsData) / lenL2TxsBytes
715 for i := 0; i < numTxsL2; i++ {
716 l2Tx, err := common.L2TxFromBytes(aux.L2TxsData[i*lenL2TxsBytes:(i+1)*lenL2TxsBytes], int(nLevels))
717 if err != nil {
718 return nil, err
719 }
720 rollupForgeBatchArgs.L2TxsData = append(rollupForgeBatchArgs.L2TxsData, l2Tx)
721 }
722 lenFeeIdxCoordinatorBytes := int(nLevels / 8) //nolint:gomnd
723 numFeeIdxCoordinator := len(aux.FeeIdxCoordinator) / lenFeeIdxCoordinatorBytes
724 for i := 0; i < numFeeIdxCoordinator; i++ {
725 var paddedFeeIdx [6]byte
726 // TODO: This check is not necessary: the first case will always work. Test it before removing the if.
727 if lenFeeIdxCoordinatorBytes < common.IdxBytesLen {
728 copy(paddedFeeIdx[6-lenFeeIdxCoordinatorBytes:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
729 } else {
730 copy(paddedFeeIdx[:], aux.FeeIdxCoordinator[i*lenFeeIdxCoordinatorBytes:(i+1)*lenFeeIdxCoordinatorBytes])
731 }
732 FeeIdxCoordinator, err := common.IdxFromBytes(paddedFeeIdx[:])
733 if err != nil {
734 return nil, err
735 }
736 rollupForgeBatchArgs.FeeIdxCoordinator = append(rollupForgeBatchArgs.FeeIdxCoordinator, FeeIdxCoordinator)
737 }
738 return &rollupForgeBatchArgs, nil
739}