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