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