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