arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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}