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