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	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}