hermez-node/eth/wdelayer.go
eth/wdelayer.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 WithdrawalDelayer "github.com/hermeznetwork/hermez-node/eth/contracts/withdrawdelayer"
17)
18
19// WDelayerConstants are the constants of the Rollup Smart Contract
20type WDelayerConstants struct {
21 // Max Withdrawal Delay
22 MaxWithdrawalDelay uint64
23 // Max Emergency mode time
24 MaxEmergencyModeTime uint64
25 // HermezRollup smartcontract address
26 HermezRollup ethCommon.Address
27}
28
29// DepositState is the state of Deposit
30type DepositState struct {
31 Amount *big.Int
32 DepositTimestamp uint64
33}
34
35// WDelayerEventDeposit is an event of the WithdrawalDelayer Smart Contract
36type WDelayerEventDeposit struct {
37 Owner ethCommon.Address
38 Token ethCommon.Address
39 Amount *big.Int
40 DepositTimestamp uint64
41}
42
43// WDelayerEventWithdraw is an event of the WithdrawalDelayer Smart Contract
44type WDelayerEventWithdraw struct {
45 Owner ethCommon.Address
46 Token ethCommon.Address
47 Amount *big.Int
48}
49
50// WDelayerEventEmergencyModeEnabled an event of the WithdrawalDelayer Smart Contract
51type WDelayerEventEmergencyModeEnabled struct {
52}
53
54// WDelayerEventNewWithdrawalDelay an event of the WithdrawalDelayer Smart Contract
55type WDelayerEventNewWithdrawalDelay struct {
56 WithdrawalDelay uint64
57}
58
59// WDelayerEventEscapeHatchWithdrawal an event of the WithdrawalDelayer Smart Contract
60type WDelayerEventEscapeHatchWithdrawal struct {
61 Who ethCommon.Address
62 To ethCommon.Address
63 Token ethCommon.Address
64}
65
66// WDelayerEventNewHermezKeeperAddress an event of the WithdrawalDelayer Smart Contract
67type WDelayerEventNewHermezKeeperAddress struct {
68 NewHermezKeeperAddress ethCommon.Address
69}
70
71// WDelayerEventNewWhiteHackGroupAddress an event of the WithdrawalDelayer Smart Contract
72type WDelayerEventNewWhiteHackGroupAddress struct {
73 NewWhiteHackGroupAddress ethCommon.Address
74}
75
76// WDelayerEventNewHermezGovernanceDAOAddress an event of the WithdrawalDelayer Smart Contract
77type WDelayerEventNewHermezGovernanceDAOAddress struct {
78 NewHermezGovernanceDAOAddress ethCommon.Address
79}
80
81// WDelayerEvents is the lis of events in a block of the WithdrawalDelayer Smart Contract
82type WDelayerEvents struct { //nolint:structcheck
83 Deposit []WDelayerEventDeposit
84 Withdraw []WDelayerEventWithdraw
85 EmergencyModeEnabled []WDelayerEventEmergencyModeEnabled
86 NewWithdrawalDelay []WDelayerEventNewWithdrawalDelay
87 EscapeHatchWithdrawal []WDelayerEventEscapeHatchWithdrawal
88 NewHermezKeeperAddress []WDelayerEventNewHermezKeeperAddress
89 NewWhiteHackGroupAddress []WDelayerEventNewWhiteHackGroupAddress
90 NewHermezGovernanceDAOAddress []WDelayerEventNewHermezGovernanceDAOAddress
91}
92
93// NewWDelayerEvents creates an empty WDelayerEvents with the slices initialized.
94func NewWDelayerEvents() WDelayerEvents {
95 return WDelayerEvents{
96 Deposit: make([]WDelayerEventDeposit, 0),
97 Withdraw: make([]WDelayerEventWithdraw, 0),
98 EmergencyModeEnabled: make([]WDelayerEventEmergencyModeEnabled, 0),
99 NewWithdrawalDelay: make([]WDelayerEventNewWithdrawalDelay, 0),
100 EscapeHatchWithdrawal: make([]WDelayerEventEscapeHatchWithdrawal, 0),
101 NewHermezKeeperAddress: make([]WDelayerEventNewHermezKeeperAddress, 0),
102 NewWhiteHackGroupAddress: make([]WDelayerEventNewWhiteHackGroupAddress, 0),
103 NewHermezGovernanceDAOAddress: make([]WDelayerEventNewHermezGovernanceDAOAddress, 0),
104 }
105}
106
107// WDelayerInterface is the inteface to WithdrawalDelayer Smart Contract
108type WDelayerInterface interface {
109 //
110 // Smart Contract Methods
111 //
112
113 WDelayerGetHermezGovernanceDAOAddress() (*ethCommon.Address, error)
114 WDelayerSetHermezGovernanceDAOAddress(newAddress ethCommon.Address) (*types.Transaction, error)
115 WDelayerGetHermezKeeperAddress() (*ethCommon.Address, error)
116 WDelayerSetHermezKeeperAddress(newAddress ethCommon.Address) (*types.Transaction, error)
117 WDelayerGetWhiteHackGroupAddress() (*ethCommon.Address, error)
118 WDelayerSetWhiteHackGroupAddress(newAddress ethCommon.Address) (*types.Transaction, error)
119 WDelayerIsEmergencyMode() (bool, error)
120 WDelayerGetWithdrawalDelay() (*big.Int, error)
121 WDelayerGetEmergencyModeStartingTime() (*big.Int, error)
122 WDelayerEnableEmergencyMode() (*types.Transaction, error)
123 WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (*types.Transaction, error)
124 WDelayerDepositInfo(owner, token ethCommon.Address) (*big.Int, uint64)
125 WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (*types.Transaction, error)
126 WDelayerWithdrawal(owner, token ethCommon.Address) (*types.Transaction, error)
127 WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address) (*types.Transaction, error)
128}
129
130//
131// Implementation
132//
133
134// WDelayerClient is the implementation of the interface to the WithdrawDelayer Smart Contract in ethereum.
135type WDelayerClient struct {
136 client *EthereumClient
137 address ethCommon.Address
138 gasLimit uint64
139 contractAbi abi.ABI
140}
141
142// NewWDelayerClient creates a new WDelayerClient
143func NewWDelayerClient(client *EthereumClient, address ethCommon.Address) (*WDelayerClient, error) {
144 contractAbi, err := abi.JSON(strings.NewReader(string(WithdrawalDelayer.WithdrawalDelayerABI)))
145 if err != nil {
146 return nil, err
147 }
148 return &WDelayerClient{
149 client: client,
150 address: address,
151 gasLimit: 1000000, //nolint:gomnd
152 contractAbi: contractAbi,
153 }, nil
154}
155
156// WDelayerGetHermezGovernanceDAOAddress is the interface to call the smart contract function
157func (c *WDelayerClient) WDelayerGetHermezGovernanceDAOAddress() (*ethCommon.Address, error) {
158 var hermezGovernanceDAOAddress ethCommon.Address
159 if err := c.client.Call(func(ec *ethclient.Client) error {
160 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
161 if err != nil {
162 return err
163 }
164 hermezGovernanceDAOAddress, err = wdelayer.GetHermezGovernanceDAOAddress(nil)
165 return err
166 }); err != nil {
167 return nil, err
168 }
169 return &hermezGovernanceDAOAddress, nil
170}
171
172// WDelayerSetHermezGovernanceDAOAddress is the interface to call the smart contract function
173func (c *WDelayerClient) WDelayerSetHermezGovernanceDAOAddress(newAddress ethCommon.Address) (*types.Transaction, error) {
174 var tx *types.Transaction
175 var err error
176 if tx, err = c.client.CallAuth(
177 c.gasLimit,
178 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
179 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
180 if err != nil {
181 return nil, err
182 }
183 return wdelayer.SetHermezGovernanceDAOAddress(auth, newAddress)
184 },
185 ); err != nil {
186 return nil, fmt.Errorf("Failed setting hermezGovernanceDAOAddress: %w", err)
187 }
188 return tx, nil
189}
190
191// WDelayerGetHermezKeeperAddress is the interface to call the smart contract function
192func (c *WDelayerClient) WDelayerGetHermezKeeperAddress() (*ethCommon.Address, error) {
193 var hermezKeeperAddress ethCommon.Address
194 if err := c.client.Call(func(ec *ethclient.Client) error {
195 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
196 if err != nil {
197 return err
198 }
199 hermezKeeperAddress, err = wdelayer.GetHermezKeeperAddress(nil)
200 return err
201 }); err != nil {
202 return nil, err
203 }
204 return &hermezKeeperAddress, nil
205}
206
207// WDelayerSetHermezKeeperAddress is the interface to call the smart contract function
208func (c *WDelayerClient) WDelayerSetHermezKeeperAddress(newAddress ethCommon.Address) (*types.Transaction, error) {
209 var tx *types.Transaction
210 var err error
211 if tx, err = c.client.CallAuth(
212 c.gasLimit,
213 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
214 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
215 if err != nil {
216 return nil, err
217 }
218 return wdelayer.SetHermezKeeperAddress(auth, newAddress)
219 },
220 ); err != nil {
221 return nil, fmt.Errorf("Failed setting hermezKeeperAddress: %w", err)
222 }
223 return tx, nil
224}
225
226// WDelayerGetWhiteHackGroupAddress is the interface to call the smart contract function
227func (c *WDelayerClient) WDelayerGetWhiteHackGroupAddress() (*ethCommon.Address, error) {
228 var whiteHackGroupAddress ethCommon.Address
229 if err := c.client.Call(func(ec *ethclient.Client) error {
230 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
231 if err != nil {
232 return err
233 }
234 whiteHackGroupAddress, err = wdelayer.GetWhiteHackGroupAddress(nil)
235 return err
236 }); err != nil {
237 return nil, err
238 }
239 return &whiteHackGroupAddress, nil
240}
241
242// WDelayerSetWhiteHackGroupAddress is the interface to call the smart contract function
243func (c *WDelayerClient) WDelayerSetWhiteHackGroupAddress(newAddress ethCommon.Address) (*types.Transaction, error) {
244 var tx *types.Transaction
245 var err error
246 if tx, err = c.client.CallAuth(
247 c.gasLimit,
248 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
249 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
250 if err != nil {
251 return nil, err
252 }
253 return wdelayer.SetWhiteHackGroupAddress(auth, newAddress)
254 },
255 ); err != nil {
256 return nil, fmt.Errorf("Failed setting whiteHackGroupAddress: %w", err)
257 }
258 return tx, nil
259}
260
261// WDelayerIsEmergencyMode is the interface to call the smart contract function
262func (c *WDelayerClient) WDelayerIsEmergencyMode() (bool, error) {
263 var ermergencyMode bool
264 if err := c.client.Call(func(ec *ethclient.Client) error {
265 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
266 if err != nil {
267 return err
268 }
269 ermergencyMode, err = wdelayer.IsEmergencyMode(nil)
270 return err
271 }); err != nil {
272 return false, err
273 }
274 return ermergencyMode, nil
275}
276
277// WDelayerGetWithdrawalDelay is the interface to call the smart contract function
278func (c *WDelayerClient) WDelayerGetWithdrawalDelay() (*big.Int, error) {
279 var withdrawalDelay *big.Int
280 if err := c.client.Call(func(ec *ethclient.Client) error {
281 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
282 if err != nil {
283 return err
284 }
285 withdrawalDelay, err = wdelayer.GetWithdrawalDelay(nil)
286 return err
287 }); err != nil {
288 return nil, err
289 }
290 return withdrawalDelay, nil
291}
292
293// WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
294func (c *WDelayerClient) WDelayerGetEmergencyModeStartingTime() (*big.Int, error) {
295 var emergencyModeStartingTime *big.Int
296 if err := c.client.Call(func(ec *ethclient.Client) error {
297 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
298 if err != nil {
299 return err
300 }
301 emergencyModeStartingTime, err = wdelayer.GetEmergencyModeStartingTime(nil)
302 return err
303 }); err != nil {
304 return nil, err
305 }
306 return emergencyModeStartingTime, nil
307}
308
309// WDelayerEnableEmergencyMode is the interface to call the smart contract function
310func (c *WDelayerClient) WDelayerEnableEmergencyMode() (*types.Transaction, error) {
311 var tx *types.Transaction
312 var err error
313 if tx, err = c.client.CallAuth(
314 c.gasLimit,
315 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
316 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
317 if err != nil {
318 return nil, err
319 }
320 return wdelayer.EnableEmergencyMode(auth)
321 },
322 ); err != nil {
323 return nil, fmt.Errorf("Failed setting enable emergency mode: %w", err)
324 }
325 return tx, nil
326}
327
328// WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
329func (c *WDelayerClient) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (*types.Transaction, error) {
330 var tx *types.Transaction
331 var err error
332 if tx, err = c.client.CallAuth(
333 c.gasLimit,
334 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
335 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
336 if err != nil {
337 return nil, err
338 }
339 return wdelayer.ChangeWithdrawalDelay(auth, newWithdrawalDelay)
340 },
341 ); err != nil {
342 return nil, fmt.Errorf("Failed setting withdrawal delay: %w", err)
343 }
344 return tx, nil
345}
346
347// WDelayerDepositInfo is the interface to call the smart contract function
348func (c *WDelayerClient) WDelayerDepositInfo(owner, token ethCommon.Address) (DepositState, error) {
349 var depositInfo DepositState
350 if err := c.client.Call(func(ec *ethclient.Client) error {
351 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
352 if err != nil {
353 return err
354 }
355 amount, depositTimestamp, err := wdelayer.DepositInfo(nil, owner, token)
356 depositInfo.Amount = amount
357 depositInfo.DepositTimestamp = depositTimestamp
358 return err
359 }); err != nil {
360 return depositInfo, err
361 }
362 return depositInfo, nil
363}
364
365// WDelayerDeposit is the interface to call the smart contract function
366func (c *WDelayerClient) WDelayerDeposit(owner, token ethCommon.Address, amount *big.Int) (*types.Transaction, error) {
367 var tx *types.Transaction
368 var err error
369 if tx, err = c.client.CallAuth(
370 c.gasLimit,
371 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
372 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
373 if err != nil {
374 return nil, err
375 }
376 return wdelayer.Deposit(auth, owner, token, amount)
377 },
378 ); err != nil {
379 return nil, fmt.Errorf("Failed deposit: %w", err)
380 }
381 return tx, nil
382}
383
384// WDelayerWithdrawal is the interface to call the smart contract function
385func (c *WDelayerClient) WDelayerWithdrawal(owner, token ethCommon.Address) (*types.Transaction, error) {
386 var tx *types.Transaction
387 var err error
388 if tx, err = c.client.CallAuth(
389 c.gasLimit,
390 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
391 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
392 if err != nil {
393 return nil, err
394 }
395 return wdelayer.Withdrawal(auth, owner, token)
396 },
397 ); err != nil {
398 return nil, fmt.Errorf("Failed withdrawal: %w", err)
399 }
400 return tx, nil
401}
402
403// WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
404func (c *WDelayerClient) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address) (*types.Transaction, error) {
405 var tx *types.Transaction
406 var err error
407 if tx, err = c.client.CallAuth(
408 c.gasLimit,
409 func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
410 wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(c.address, ec)
411 if err != nil {
412 return nil, err
413 }
414 return wdelayer.EscapeHatchWithdrawal(auth, to, token)
415 },
416 ); err != nil {
417 return nil, fmt.Errorf("Failed escapeHatchWithdrawal: %w", err)
418 }
419 return tx, nil
420}
421
422var (
423 logDeposit = crypto.Keccak256Hash([]byte("Deposit(address,address,uint192,uint64)"))
424 logWithdraw = crypto.Keccak256Hash([]byte("Withdraw(address,address,uint192)"))
425 logEmergencyModeEnabled = crypto.Keccak256Hash([]byte("EmergencyModeEnabled()"))
426 logNewWithdrawalDelay = crypto.Keccak256Hash([]byte("NewWithdrawalDelay(uint64)"))
427 logEscapeHatchWithdrawal = crypto.Keccak256Hash([]byte("EscapeHatchWithdrawal(address,address,address)"))
428 logNewHermezKeeperAddress = crypto.Keccak256Hash([]byte("NewHermezKeeperAddress(address)"))
429 logNewWhiteHackGroupAddress = crypto.Keccak256Hash([]byte("NewWhiteHackGroupAddress(address)"))
430 logNewHermezGovernanceDAOAddress = crypto.Keccak256Hash([]byte("NewHermezGovernanceDAOAddress(address)"))
431)
432
433// WDelayerEventsByBlock returns the events in a block that happened in the WDelayer Smart Contract
434func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error) {
435 var wdelayerEvents WDelayerEvents
436 var blockHash ethCommon.Hash
437
438 query := ethereum.FilterQuery{
439 FromBlock: big.NewInt(blockNum),
440 ToBlock: big.NewInt(blockNum),
441 Addresses: []ethCommon.Address{
442 c.address,
443 },
444 BlockHash: nil,
445 Topics: [][]ethCommon.Hash{},
446 }
447
448 logs, err := c.client.client.FilterLogs(context.Background(), query)
449 if err != nil {
450 fmt.Println(err)
451 }
452 if len(logs) > 0 {
453 blockHash = logs[0].BlockHash
454 }
455 for _, vLog := range logs {
456 if vLog.BlockHash != blockHash {
457 return nil, nil, err
458 }
459 switch vLog.Topics[0] {
460 case logDeposit:
461 var deposit WDelayerEventDeposit
462 err := c.contractAbi.Unpack(&deposit, "Deposit", vLog.Data)
463 if err != nil {
464 return nil, nil, err
465 }
466 deposit.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
467 deposit.Token = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
468 wdelayerEvents.Deposit = append(wdelayerEvents.Deposit, deposit)
469
470 case logWithdraw:
471 var withdraw WDelayerEventWithdraw
472 err := c.contractAbi.Unpack(&withdraw, "Withdraw", vLog.Data)
473 if err != nil {
474 return nil, nil, err
475 }
476 withdraw.Token = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
477 withdraw.Owner = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
478 wdelayerEvents.Withdraw = append(wdelayerEvents.Withdraw, withdraw)
479
480 case logEmergencyModeEnabled:
481 var emergencyModeEnabled WDelayerEventEmergencyModeEnabled
482 wdelayerEvents.EmergencyModeEnabled = append(wdelayerEvents.EmergencyModeEnabled, emergencyModeEnabled)
483
484 case logNewWithdrawalDelay:
485 var withdrawalDelay WDelayerEventNewWithdrawalDelay
486 err := c.contractAbi.Unpack(&withdrawalDelay, "NewWithdrawalDelay", vLog.Data)
487 if err != nil {
488 return nil, nil, err
489 }
490 wdelayerEvents.NewWithdrawalDelay = append(wdelayerEvents.NewWithdrawalDelay, withdrawalDelay)
491
492 case logEscapeHatchWithdrawal:
493 var escapeHatchWithdrawal WDelayerEventEscapeHatchWithdrawal
494 escapeHatchWithdrawal.Who = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
495 escapeHatchWithdrawal.To = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
496 escapeHatchWithdrawal.Token = ethCommon.BytesToAddress(vLog.Topics[3].Bytes())
497 wdelayerEvents.EscapeHatchWithdrawal = append(wdelayerEvents.EscapeHatchWithdrawal, escapeHatchWithdrawal)
498
499 case logNewHermezKeeperAddress:
500 var keeperAddress WDelayerEventNewHermezKeeperAddress
501 err := c.contractAbi.Unpack(&keeperAddress, "NewHermezKeeperAddress", vLog.Data)
502 if err != nil {
503 return nil, nil, err
504 }
505 wdelayerEvents.NewHermezKeeperAddress = append(wdelayerEvents.NewHermezKeeperAddress, keeperAddress)
506
507 case logNewWhiteHackGroupAddress:
508 var whiteHackGroupAddress WDelayerEventNewWhiteHackGroupAddress
509 err := c.contractAbi.Unpack(&whiteHackGroupAddress, "NewWhiteHackGroupAddress", vLog.Data)
510 if err != nil {
511 return nil, nil, err
512 }
513 wdelayerEvents.NewWhiteHackGroupAddress = append(wdelayerEvents.NewWhiteHackGroupAddress, whiteHackGroupAddress)
514
515 case logNewHermezGovernanceDAOAddress:
516 var governanceDAOAddress WDelayerEventNewHermezGovernanceDAOAddress
517 err := c.contractAbi.Unpack(&governanceDAOAddress, "NewHermezGovernanceDAOAddress", vLog.Data)
518 if err != nil {
519 return nil, nil, err
520 }
521 wdelayerEvents.NewHermezGovernanceDAOAddress = append(wdelayerEvents.NewHermezGovernanceDAOAddress, governanceDAOAddress)
522 }
523 }
524 return &wdelayerEvents, &blockHash, nil
525}