arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/eth/auction.go
eth/auction.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	HermezAuctionProtocol "github.com/hermeznetwork/hermez-node/eth/contracts/auction"
 18	HEZ "github.com/hermeznetwork/hermez-node/eth/contracts/tokenHEZ"
 19	"github.com/hermeznetwork/hermez-node/log"
 20	"github.com/hermeznetwork/tracerr"
 21)
 22
 23// SlotState is the state of a slot
 24type SlotState struct {
 25	Bidder           ethCommon.Address
 26	ForgerCommitment bool
 27	Fulfilled        bool
 28	BidAmount        *big.Int
 29	ClosedMinBid     *big.Int
 30}
 31
 32// NewSlotState returns an empty SlotState
 33func NewSlotState() *SlotState {
 34	return &SlotState{
 35		Bidder:           ethCommon.Address{},
 36		Fulfilled:        false,
 37		ForgerCommitment: false,
 38		BidAmount:        big.NewInt(0),
 39		ClosedMinBid:     big.NewInt(0),
 40	}
 41}
 42
 43// Coordinator is the details of the Coordinator identified by the forger address
 44type Coordinator struct {
 45	Forger ethCommon.Address
 46	URL    string
 47}
 48
 49// AuctionState represents the state of the Rollup in the Smart Contract
 50type AuctionState struct {
 51	// Mapping to control slot state
 52	Slots map[int64]*SlotState
 53	// Mapping to control balances pending to claim
 54	PendingBalances map[ethCommon.Address]*big.Int
 55	// Mapping to register all the coordinators. The address used for the mapping is the forger address
 56	Coordinators map[ethCommon.Address]*Coordinator
 57}
 58
 59// AuctionEventInitialize is the InitializeHermezAuctionProtocolEvent event of
 60// the Smart Contract
 61type AuctionEventInitialize struct {
 62	DonationAddress        ethCommon.Address
 63	BootCoordinatorAddress ethCommon.Address
 64	BootCoordinatorURL     string
 65	Outbidding             uint16
 66	SlotDeadline           uint8
 67	ClosedAuctionSlots     uint16
 68	OpenAuctionSlots       uint16
 69	AllocationRatio        [3]uint16
 70}
 71
 72// AuctionVariables returns the AuctionVariables from the initialize event
 73func (ei *AuctionEventInitialize) AuctionVariables(
 74	InitialMinimalBidding *big.Int) *common.AuctionVariables {
 75	return &common.AuctionVariables{
 76		EthBlockNum:        0,
 77		DonationAddress:    ei.DonationAddress,
 78		BootCoordinator:    ei.BootCoordinatorAddress,
 79		BootCoordinatorURL: ei.BootCoordinatorURL,
 80		DefaultSlotSetBid: [6]*big.Int{
 81			InitialMinimalBidding, InitialMinimalBidding, InitialMinimalBidding,
 82			InitialMinimalBidding, InitialMinimalBidding, InitialMinimalBidding,
 83		},
 84		DefaultSlotSetBidSlotNum: 0,
 85		ClosedAuctionSlots:       ei.ClosedAuctionSlots,
 86		OpenAuctionSlots:         ei.OpenAuctionSlots,
 87		AllocationRatio:          ei.AllocationRatio,
 88		Outbidding:               ei.Outbidding,
 89		SlotDeadline:             ei.SlotDeadline,
 90	}
 91}
 92
 93// AuctionEventNewBid is an event of the Auction Smart Contract
 94type AuctionEventNewBid struct {
 95	Slot      int64
 96	BidAmount *big.Int
 97	Bidder    ethCommon.Address
 98}
 99
100// AuctionEventNewSlotDeadline is an event of the Auction Smart Contract
101type AuctionEventNewSlotDeadline struct {
102	NewSlotDeadline uint8
103}
104
105// AuctionEventNewClosedAuctionSlots is an event of the Auction Smart Contract
106type AuctionEventNewClosedAuctionSlots struct {
107	NewClosedAuctionSlots uint16
108}
109
110// AuctionEventNewOutbidding is an event of the Auction Smart Contract
111type AuctionEventNewOutbidding struct {
112	NewOutbidding uint16
113}
114
115// AuctionEventNewDonationAddress is an event of the Auction Smart Contract
116type AuctionEventNewDonationAddress struct {
117	NewDonationAddress ethCommon.Address
118}
119
120// AuctionEventNewBootCoordinator is an event of the Auction Smart Contract
121type AuctionEventNewBootCoordinator struct {
122	NewBootCoordinator    ethCommon.Address
123	NewBootCoordinatorURL string
124}
125
126// AuctionEventNewOpenAuctionSlots is an event of the Auction Smart Contract
127type AuctionEventNewOpenAuctionSlots struct {
128	NewOpenAuctionSlots uint16
129}
130
131// AuctionEventNewAllocationRatio is an event of the Auction Smart Contract
132type AuctionEventNewAllocationRatio struct {
133	NewAllocationRatio [3]uint16
134}
135
136// AuctionEventSetCoordinator is an event of the Auction Smart Contract
137type AuctionEventSetCoordinator struct {
138	BidderAddress  ethCommon.Address
139	ForgerAddress  ethCommon.Address
140	CoordinatorURL string
141}
142
143// AuctionEventNewForgeAllocated is an event of the Auction Smart Contract
144type AuctionEventNewForgeAllocated struct {
145	Bidder           ethCommon.Address
146	Forger           ethCommon.Address
147	SlotToForge      int64
148	BurnAmount       *big.Int
149	DonationAmount   *big.Int
150	GovernanceAmount *big.Int
151}
152
153// AuctionEventNewDefaultSlotSetBid is an event of the Auction Smart Contract
154type AuctionEventNewDefaultSlotSetBid struct {
155	SlotSet          int64
156	NewInitialMinBid *big.Int
157}
158
159// AuctionEventNewForge is an event of the Auction Smart Contract
160type AuctionEventNewForge struct {
161	Forger      ethCommon.Address
162	SlotToForge int64
163}
164
165// AuctionEventHEZClaimed is an event of the Auction Smart Contract
166type AuctionEventHEZClaimed struct {
167	Owner  ethCommon.Address
168	Amount *big.Int
169}
170
171// AuctionEvents is the list of events in a block of the Auction Smart Contract
172type AuctionEvents struct {
173	NewBid                []AuctionEventNewBid
174	NewSlotDeadline       []AuctionEventNewSlotDeadline
175	NewClosedAuctionSlots []AuctionEventNewClosedAuctionSlots
176	NewOutbidding         []AuctionEventNewOutbidding
177	NewDonationAddress    []AuctionEventNewDonationAddress
178	NewBootCoordinator    []AuctionEventNewBootCoordinator
179	NewOpenAuctionSlots   []AuctionEventNewOpenAuctionSlots
180	NewAllocationRatio    []AuctionEventNewAllocationRatio
181	SetCoordinator        []AuctionEventSetCoordinator
182	NewForgeAllocated     []AuctionEventNewForgeAllocated
183	NewDefaultSlotSetBid  []AuctionEventNewDefaultSlotSetBid
184	NewForge              []AuctionEventNewForge
185	HEZClaimed            []AuctionEventHEZClaimed
186}
187
188// NewAuctionEvents creates an empty AuctionEvents with the slices initialized.
189func NewAuctionEvents() AuctionEvents {
190	return AuctionEvents{
191		NewBid:                make([]AuctionEventNewBid, 0),
192		NewSlotDeadline:       make([]AuctionEventNewSlotDeadline, 0),
193		NewClosedAuctionSlots: make([]AuctionEventNewClosedAuctionSlots, 0),
194		NewOutbidding:         make([]AuctionEventNewOutbidding, 0),
195		NewDonationAddress:    make([]AuctionEventNewDonationAddress, 0),
196		NewBootCoordinator:    make([]AuctionEventNewBootCoordinator, 0),
197		NewOpenAuctionSlots:   make([]AuctionEventNewOpenAuctionSlots, 0),
198		NewAllocationRatio:    make([]AuctionEventNewAllocationRatio, 0),
199		SetCoordinator:        make([]AuctionEventSetCoordinator, 0),
200		NewForgeAllocated:     make([]AuctionEventNewForgeAllocated, 0),
201		NewDefaultSlotSetBid:  make([]AuctionEventNewDefaultSlotSetBid, 0),
202		NewForge:              make([]AuctionEventNewForge, 0),
203		HEZClaimed:            make([]AuctionEventHEZClaimed, 0),
204	}
205}
206
207// AuctionInterface is the inteface to to Auction Smart Contract
208type AuctionInterface interface {
209	//
210	// Smart Contract Methods
211	//
212
213	// Getter/Setter, where Setter is onlyOwner
214	AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error)
215	AuctionGetSlotDeadline() (uint8, error)
216	AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error)
217	AuctionGetOpenAuctionSlots() (uint16, error)
218	AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error)
219	AuctionGetClosedAuctionSlots() (uint16, error)
220	AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error)
221	AuctionGetOutbidding() (uint16, error)
222	AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error)
223	AuctionGetAllocationRatio() ([3]uint16, error)
224	AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error)
225	AuctionGetDonationAddress() (*ethCommon.Address, error)
226	AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address,
227		newBootCoordinatorURL string) (*types.Transaction, error)
228	AuctionGetBootCoordinator() (*ethCommon.Address, error)
229	AuctionChangeDefaultSlotSetBid(slotSet int64,
230		newInitialMinBid *big.Int) (*types.Transaction, error)
231
232	// Coordinator Management
233	AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (*types.Transaction,
234		error)
235
236	// Slot Info
237	AuctionGetSlotNumber(blockNum int64) (int64, error)
238	AuctionGetCurrentSlotNumber() (int64, error)
239	AuctionGetMinBidBySlot(slot int64) (*big.Int, error)
240	AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error)
241	AuctionGetSlotSet(slot int64) (*big.Int, error)
242
243	// Bidding
244	AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (
245		tx *types.Transaction, err error)
246	AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
247		maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error)
248
249	// Forge
250	AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error)
251	AuctionForge(forger ethCommon.Address) (*types.Transaction, error)
252
253	// Fees
254	AuctionClaimHEZ() (*types.Transaction, error)
255	AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error)
256
257	//
258	// Smart Contract Status
259	//
260
261	AuctionConstants() (*common.AuctionConstants, error)
262	AuctionEventsByBlock(blockNum int64, blockHash *ethCommon.Hash) (*AuctionEvents, error)
263	AuctionEventInit(genesisBlockNum int64) (*AuctionEventInitialize, int64, error)
264}
265
266//
267// Implementation
268//
269
270// AuctionClient is the implementation of the interface to the Auction Smart Contract in ethereum.
271type AuctionClient struct {
272	client      *EthereumClient
273	chainID     *big.Int
274	address     ethCommon.Address
275	tokenHEZCfg TokenConfig
276	auction     *HermezAuctionProtocol.HermezAuctionProtocol
277	tokenHEZ    *HEZ.HEZ
278	contractAbi abi.ABI
279	opts        *bind.CallOpts
280}
281
282// NewAuctionClient creates a new AuctionClient.  `tokenAddress` is the address of the HEZ tokens.
283func NewAuctionClient(client *EthereumClient, address ethCommon.Address,
284	tokenHEZCfg TokenConfig) (*AuctionClient, error) {
285	contractAbi, err :=
286		abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI)))
287	if err != nil {
288		return nil, tracerr.Wrap(err)
289	}
290	auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(address, client.Client())
291	if err != nil {
292		return nil, tracerr.Wrap(err)
293	}
294	tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
295	if err != nil {
296		return nil, tracerr.Wrap(err)
297	}
298	chainID, err := client.EthChainID()
299	if err != nil {
300		return nil, tracerr.Wrap(err)
301	}
302	return &AuctionClient{
303		client:      client,
304		chainID:     chainID,
305		address:     address,
306		tokenHEZCfg: tokenHEZCfg,
307		auction:     auction,
308		tokenHEZ:    tokenHEZ,
309		contractAbi: contractAbi,
310		opts:        newCallOpts(),
311	}, nil
312}
313
314// AuctionSetSlotDeadline is the interface to call the smart contract function
315func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
316	var tx *types.Transaction
317	var err error
318	if tx, err = c.client.CallAuth(
319		0,
320		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
321			return c.auction.SetSlotDeadline(auth, newDeadline)
322		},
323	); err != nil {
324		return nil, tracerr.Wrap(fmt.Errorf("Failed setting slotDeadline: %w", err))
325	}
326	return tx, nil
327}
328
329// AuctionGetSlotDeadline is the interface to call the smart contract function
330func (c *AuctionClient) AuctionGetSlotDeadline() (slotDeadline uint8, err error) {
331	if err := c.client.Call(func(ec *ethclient.Client) error {
332		slotDeadline, err = c.auction.GetSlotDeadline(c.opts)
333		return tracerr.Wrap(err)
334	}); err != nil {
335		return 0, tracerr.Wrap(err)
336	}
337	return slotDeadline, nil
338}
339
340// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
341func (c *AuctionClient) AuctionSetOpenAuctionSlots(
342	newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
343	if tx, err = c.client.CallAuth(
344		0,
345		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
346			return c.auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
347		},
348	); err != nil {
349		return nil, tracerr.Wrap(fmt.Errorf("Failed setting openAuctionSlots: %w", err))
350	}
351	return tx, nil
352}
353
354// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
355func (c *AuctionClient) AuctionGetOpenAuctionSlots() (openAuctionSlots uint16, err error) {
356	if err := c.client.Call(func(ec *ethclient.Client) error {
357		openAuctionSlots, err = c.auction.GetOpenAuctionSlots(c.opts)
358		return tracerr.Wrap(err)
359	}); err != nil {
360		return 0, tracerr.Wrap(err)
361	}
362	return openAuctionSlots, nil
363}
364
365// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
366func (c *AuctionClient) AuctionSetClosedAuctionSlots(
367	newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
368	if tx, err = c.client.CallAuth(
369		0,
370		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
371			return c.auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
372		},
373	); err != nil {
374		return nil, tracerr.Wrap(fmt.Errorf("Failed setting closedAuctionSlots: %w", err))
375	}
376	return tx, nil
377}
378
379// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
380func (c *AuctionClient) AuctionGetClosedAuctionSlots() (closedAuctionSlots uint16, err error) {
381	if err := c.client.Call(func(ec *ethclient.Client) error {
382		closedAuctionSlots, err = c.auction.GetClosedAuctionSlots(c.opts)
383		return tracerr.Wrap(err)
384	}); err != nil {
385		return 0, tracerr.Wrap(err)
386	}
387	return closedAuctionSlots, nil
388}
389
390// AuctionSetOutbidding is the interface to call the smart contract function
391func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction,
392	err error) {
393	if tx, err = c.client.CallAuth(
394		12500000, //nolint:gomnd
395		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
396			return c.auction.SetOutbidding(auth, newOutbidding)
397		},
398	); err != nil {
399		return nil, tracerr.Wrap(fmt.Errorf("Failed setting setOutbidding: %w", err))
400	}
401	return tx, nil
402}
403
404// AuctionGetOutbidding is the interface to call the smart contract function
405func (c *AuctionClient) AuctionGetOutbidding() (outbidding uint16, err error) {
406	if err := c.client.Call(func(ec *ethclient.Client) error {
407		outbidding, err = c.auction.GetOutbidding(c.opts)
408		return tracerr.Wrap(err)
409	}); err != nil {
410		return 0, tracerr.Wrap(err)
411	}
412	return outbidding, nil
413}
414
415// AuctionSetAllocationRatio is the interface to call the smart contract function
416func (c *AuctionClient) AuctionSetAllocationRatio(
417	newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
418	if tx, err = c.client.CallAuth(
419		0,
420		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
421			return c.auction.SetAllocationRatio(auth, newAllocationRatio)
422		},
423	); err != nil {
424		return nil, tracerr.Wrap(fmt.Errorf("Failed setting allocationRatio: %w", err))
425	}
426	return tx, nil
427}
428
429// AuctionGetAllocationRatio is the interface to call the smart contract function
430func (c *AuctionClient) AuctionGetAllocationRatio() (allocationRation [3]uint16, err error) {
431	if err := c.client.Call(func(ec *ethclient.Client) error {
432		allocationRation, err = c.auction.GetAllocationRatio(c.opts)
433		return tracerr.Wrap(err)
434	}); err != nil {
435		return [3]uint16{}, tracerr.Wrap(err)
436	}
437	return allocationRation, nil
438}
439
440// AuctionSetDonationAddress is the interface to call the smart contract function
441func (c *AuctionClient) AuctionSetDonationAddress(
442	newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
443	if tx, err = c.client.CallAuth(
444		0,
445		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
446			return c.auction.SetDonationAddress(auth, newDonationAddress)
447		},
448	); err != nil {
449		return nil, tracerr.Wrap(fmt.Errorf("Failed setting donationAddress: %w", err))
450	}
451	return tx, nil
452}
453
454// AuctionGetDonationAddress is the interface to call the smart contract function
455func (c *AuctionClient) AuctionGetDonationAddress() (donationAddress *ethCommon.Address,
456	err error) {
457	var _donationAddress ethCommon.Address
458	if err := c.client.Call(func(ec *ethclient.Client) error {
459		_donationAddress, err = c.auction.GetDonationAddress(c.opts)
460		return tracerr.Wrap(err)
461	}); err != nil {
462		return nil, tracerr.Wrap(err)
463	}
464	return &_donationAddress, nil
465}
466
467// AuctionSetBootCoordinator is the interface to call the smart contract function
468func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address,
469	newBootCoordinatorURL string) (tx *types.Transaction, err error) {
470	if tx, err = c.client.CallAuth(
471		0,
472		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
473			return c.auction.SetBootCoordinator(auth, newBootCoordinator,
474				newBootCoordinatorURL)
475		},
476	); err != nil {
477		return nil, tracerr.Wrap(fmt.Errorf("Failed setting bootCoordinator: %w", err))
478	}
479	return tx, nil
480}
481
482// AuctionGetBootCoordinator is the interface to call the smart contract function
483func (c *AuctionClient) AuctionGetBootCoordinator() (bootCoordinator *ethCommon.Address,
484	err error) {
485	var _bootCoordinator ethCommon.Address
486	if err := c.client.Call(func(ec *ethclient.Client) error {
487		_bootCoordinator, err = c.auction.GetBootCoordinator(c.opts)
488		return tracerr.Wrap(err)
489	}); err != nil {
490		return nil, tracerr.Wrap(err)
491	}
492	return &_bootCoordinator, nil
493}
494
495// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
496func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64,
497	newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
498	if tx, err = c.client.CallAuth(
499		0,
500		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
501			slotSetToSend := big.NewInt(slotSet)
502			return c.auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
503		},
504	); err != nil {
505		return nil, tracerr.Wrap(fmt.Errorf("Failed changing slotSet Bid: %w", err))
506	}
507	return tx, nil
508}
509
510// AuctionGetClaimableHEZ is the interface to call the smart contract function
511func (c *AuctionClient) AuctionGetClaimableHEZ(
512	claimAddress ethCommon.Address) (claimableHEZ *big.Int, err error) {
513	if err := c.client.Call(func(ec *ethclient.Client) error {
514		claimableHEZ, err = c.auction.GetClaimableHEZ(c.opts, claimAddress)
515		return tracerr.Wrap(err)
516	}); err != nil {
517		return nil, tracerr.Wrap(err)
518	}
519	return claimableHEZ, nil
520}
521
522// AuctionSetCoordinator is the interface to call the smart contract function
523func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address,
524	coordinatorURL string) (tx *types.Transaction, err error) {
525	if tx, err = c.client.CallAuth(
526		0,
527		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
528			return c.auction.SetCoordinator(auth, forger, coordinatorURL)
529		},
530	); err != nil {
531		return nil, tracerr.Wrap(fmt.Errorf("Failed set coordinator: %w", err))
532	}
533	return tx, nil
534}
535
536// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
537func (c *AuctionClient) AuctionGetCurrentSlotNumber() (currentSlotNumber int64, err error) {
538	var _currentSlotNumber *big.Int
539	if err := c.client.Call(func(ec *ethclient.Client) error {
540		_currentSlotNumber, err = c.auction.GetCurrentSlotNumber(c.opts)
541		return tracerr.Wrap(err)
542	}); err != nil {
543		return 0, tracerr.Wrap(err)
544	}
545	return _currentSlotNumber.Int64(), nil
546}
547
548// AuctionGetMinBidBySlot is the interface to call the smart contract function
549func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (minBid *big.Int, err error) {
550	if err := c.client.Call(func(ec *ethclient.Client) error {
551		slotToSend := big.NewInt(slot)
552		minBid, err = c.auction.GetMinBidBySlot(c.opts, slotToSend)
553		return tracerr.Wrap(err)
554	}); err != nil {
555		return big.NewInt(0), tracerr.Wrap(err)
556	}
557	return minBid, nil
558}
559
560// AuctionGetSlotSet is the interface to call the smart contract function
561func (c *AuctionClient) AuctionGetSlotSet(slot int64) (slotSet *big.Int, err error) {
562	if err := c.client.Call(func(ec *ethclient.Client) error {
563		slotToSend := big.NewInt(slot)
564		slotSet, err = c.auction.GetSlotSet(c.opts, slotToSend)
565		return tracerr.Wrap(err)
566	}); err != nil {
567		return big.NewInt(0), tracerr.Wrap(err)
568	}
569	return slotSet, nil
570}
571
572// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
573func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (minBidSlotSet *big.Int,
574	err error) {
575	if err := c.client.Call(func(ec *ethclient.Client) error {
576		minBidSlotSet, err = c.auction.GetDefaultSlotSetBid(c.opts, slotSet)
577		return tracerr.Wrap(err)
578	}); err != nil {
579		return big.NewInt(0), tracerr.Wrap(err)
580	}
581	return minBidSlotSet, nil
582}
583
584// AuctionGetSlotNumber is the interface to call the smart contract function
585func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (slot int64, err error) {
586	var _slot *big.Int
587	if err := c.client.Call(func(ec *ethclient.Client) error {
588		_slot, err = c.auction.GetSlotNumber(c.opts, big.NewInt(blockNum))
589		return tracerr.Wrap(err)
590	}); err != nil {
591		return 0, tracerr.Wrap(err)
592	}
593	return _slot.Int64(), nil
594}
595
596// AuctionBid is the interface to call the smart contract function
597func (c *AuctionClient) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int,
598	deadline *big.Int) (tx *types.Transaction, err error) {
599	if tx, err = c.client.CallAuth(
600		0,
601		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
602			owner := c.client.account.Address
603			spender := c.address
604			nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
605			if err != nil {
606				return nil, tracerr.Wrap(err)
607			}
608			tokenName := c.tokenHEZCfg.Name
609			tokenAddr := c.tokenHEZCfg.Address
610			digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID,
611				amount, nonce, deadline, tokenName)
612			signature, _ := c.client.ks.SignHash(*c.client.account, digest)
613			permit := createPermit(owner, spender, amount, deadline, digest, signature)
614			_slot := big.NewInt(slot)
615			return c.auction.ProcessBid(auth, amount, _slot, bidAmount, permit)
616		},
617	); err != nil {
618		return nil, tracerr.Wrap(fmt.Errorf("Failed bid: %w", err))
619	}
620	return tx, nil
621}
622
623// AuctionMultiBid is the interface to call the smart contract function
624func (c *AuctionClient) AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64,
625	slotSets [6]bool, maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error) {
626	if tx, err = c.client.CallAuth(
627		1000000, //nolint:gomnd
628		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
629			owner := c.client.account.Address
630			spender := c.address
631			nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
632			if err != nil {
633				return nil, tracerr.Wrap(err)
634			}
635			tokenName := c.tokenHEZCfg.Name
636			tokenAddr := c.tokenHEZCfg.Address
637
638			digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID,
639				amount, nonce, deadline, tokenName)
640			signature, _ := c.client.ks.SignHash(*c.client.account, digest)
641			permit := createPermit(owner, spender, amount, deadline, digest, signature)
642			_startingSlot := big.NewInt(startingSlot)
643			_endingSlot := big.NewInt(endingSlot)
644			return c.auction.ProcessMultiBid(auth, amount, _startingSlot, _endingSlot,
645				slotSets, maxBid, minBid, permit)
646		},
647	); err != nil {
648		return nil, tracerr.Wrap(fmt.Errorf("Failed multibid: %w", err))
649	}
650	return tx, nil
651}
652
653// AuctionCanForge is the interface to call the smart contract function
654func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (canForge bool,
655	err error) {
656	if err := c.client.Call(func(ec *ethclient.Client) error {
657		canForge, err = c.auction.CanForge(c.opts, forger, big.NewInt(blockNum))
658		return tracerr.Wrap(err)
659	}); err != nil {
660		return false, tracerr.Wrap(err)
661	}
662	return canForge, nil
663}
664
665// AuctionClaimHEZ is the interface to call the smart contract function
666func (c *AuctionClient) AuctionClaimHEZ() (tx *types.Transaction, err error) {
667	if tx, err = c.client.CallAuth(
668		0,
669		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
670			return c.auction.ClaimHEZ(auth)
671		},
672	); err != nil {
673		return nil, tracerr.Wrap(fmt.Errorf("Failed claim HEZ: %w", err))
674	}
675	return tx, nil
676}
677
678// AuctionForge is the interface to call the smart contract function
679func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
680	if tx, err = c.client.CallAuth(
681		0,
682		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
683			return c.auction.Forge(auth, forger)
684		},
685	); err != nil {
686		return nil, tracerr.Wrap(fmt.Errorf("Failed forge: %w", err))
687	}
688	return tx, nil
689}
690
691// AuctionConstants returns the Constants of the Auction Smart Contract
692func (c *AuctionClient) AuctionConstants() (auctionConstants *common.AuctionConstants, err error) {
693	auctionConstants = new(common.AuctionConstants)
694	if err := c.client.Call(func(ec *ethclient.Client) error {
695		auctionConstants.BlocksPerSlot, err = c.auction.BLOCKSPERSLOT(c.opts)
696		if err != nil {
697			return tracerr.Wrap(err)
698		}
699		genesisBlock, err := c.auction.GenesisBlock(c.opts)
700		if err != nil {
701			return tracerr.Wrap(err)
702		}
703		auctionConstants.GenesisBlockNum = genesisBlock.Int64()
704		auctionConstants.HermezRollup, err = c.auction.HermezRollup(c.opts)
705		if err != nil {
706			return tracerr.Wrap(err)
707		}
708		auctionConstants.InitialMinimalBidding, err =
709			c.auction.INITIALMINIMALBIDDING(c.opts)
710		if err != nil {
711			return tracerr.Wrap(err)
712		}
713		auctionConstants.GovernanceAddress, err = c.auction.GovernanceAddress(c.opts)
714		if err != nil {
715			return tracerr.Wrap(err)
716		}
717		auctionConstants.TokenHEZ, err = c.auction.TokenHEZ(c.opts)
718		if err != nil {
719			return tracerr.Wrap(err)
720		}
721		return nil
722	}); err != nil {
723		return nil, tracerr.Wrap(err)
724	}
725	return auctionConstants, nil
726}
727
728// AuctionVariables returns the variables of the Auction Smart Contract
729func (c *AuctionClient) AuctionVariables() (auctionVariables *common.AuctionVariables, err error) {
730	auctionVariables = new(common.AuctionVariables)
731	if err := c.client.Call(func(ec *ethclient.Client) error {
732		auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
733		if err != nil {
734			return tracerr.Wrap(err)
735		}
736		bootCoordinator, err := c.AuctionGetBootCoordinator()
737		if err != nil {
738			return tracerr.Wrap(err)
739		}
740		auctionVariables.BootCoordinator = *bootCoordinator
741		auctionVariables.BootCoordinatorURL, err = c.auction.BootCoordinatorURL(c.opts)
742		if err != nil {
743			return tracerr.Wrap(err)
744		}
745		auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
746		if err != nil {
747			return tracerr.Wrap(err)
748		}
749		var defaultSlotSetBid [6]*big.Int
750		for i := uint8(0); i < 6; i++ {
751			bid, err := c.AuctionGetDefaultSlotSetBid(i)
752			if err != nil {
753				return tracerr.Wrap(err)
754			}
755			defaultSlotSetBid[i] = bid
756		}
757		auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
758		donationAddress, err := c.AuctionGetDonationAddress()
759		if err != nil {
760			return tracerr.Wrap(err)
761		}
762		auctionVariables.DonationAddress = *donationAddress
763		auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
764		if err != nil {
765			return tracerr.Wrap(err)
766		}
767		auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
768		if err != nil {
769			return tracerr.Wrap(err)
770		}
771		auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
772		return tracerr.Wrap(err)
773	}); err != nil {
774		return nil, tracerr.Wrap(err)
775	}
776	return auctionVariables, nil
777}
778
779var (
780	logAuctionNewBid = crypto.Keccak256Hash([]byte(
781		"NewBid(uint128,uint128,address)"))
782	logAuctionNewSlotDeadline = crypto.Keccak256Hash([]byte(
783		"NewSlotDeadline(uint8)"))
784	logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte(
785		"NewClosedAuctionSlots(uint16)"))
786	logAuctionNewOutbidding = crypto.Keccak256Hash([]byte(
787		"NewOutbidding(uint16)"))
788	logAuctionNewDonationAddress = crypto.Keccak256Hash([]byte(
789		"NewDonationAddress(address)"))
790	logAuctionNewBootCoordinator = crypto.Keccak256Hash([]byte(
791		"NewBootCoordinator(address,string)"))
792	logAuctionNewOpenAuctionSlots = crypto.Keccak256Hash([]byte(
793		"NewOpenAuctionSlots(uint16)"))
794	logAuctionNewAllocationRatio = crypto.Keccak256Hash([]byte(
795		"NewAllocationRatio(uint16[3])"))
796	logAuctionSetCoordinator = crypto.Keccak256Hash([]byte(
797		"SetCoordinator(address,address,string)"))
798	logAuctionNewForgeAllocated = crypto.Keccak256Hash([]byte(
799		"NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
800	logAuctionNewDefaultSlotSetBid = crypto.Keccak256Hash([]byte(
801		"NewDefaultSlotSetBid(uint128,uint128)"))
802	logAuctionNewForge = crypto.Keccak256Hash([]byte(
803		"NewForge(address,uint128)"))
804	logAuctionHEZClaimed = crypto.Keccak256Hash([]byte(
805		"HEZClaimed(address,uint128)"))
806	logAuctionInitialize = crypto.Keccak256Hash([]byte(
807		"InitializeHermezAuctionProtocolEvent(address,address,string," +
808			"uint16,uint8,uint16,uint16,uint16[3])"))
809)
810
811// AuctionEventInit returns the initialize event with its corresponding block number
812func (c *AuctionClient) AuctionEventInit(genesisBlockNum int64) (*AuctionEventInitialize, int64, error) {
813	query := ethereum.FilterQuery{
814		Addresses: []ethCommon.Address{
815			c.address,
816		},
817		FromBlock: big.NewInt(max(0, genesisBlockNum-blocksPerDay)),
818		ToBlock:   big.NewInt(genesisBlockNum),
819		Topics:    [][]ethCommon.Hash{{logAuctionInitialize}},
820	}
821	logs, err := c.client.client.FilterLogs(context.Background(), query)
822	if err != nil {
823		return nil, 0, tracerr.Wrap(err)
824	}
825	if len(logs) != 1 {
826		return nil, 0,
827			tracerr.Wrap(fmt.Errorf("no event of type InitializeHermezAuctionProtocolEvent found"))
828	}
829	vLog := logs[0]
830	if vLog.Topics[0] != logAuctionInitialize {
831		return nil, 0, tracerr.Wrap(fmt.Errorf("event is not InitializeHermezAuctionProtocolEvent"))
832	}
833
834	var auctionInit AuctionEventInitialize
835	if err := c.contractAbi.UnpackIntoInterface(&auctionInit,
836		"InitializeHermezAuctionProtocolEvent", vLog.Data); err != nil {
837		return nil, 0, tracerr.Wrap(err)
838	}
839	return &auctionInit, int64(vLog.BlockNumber), tracerr.Wrap(err)
840}
841
842// AuctionEventsByBlock returns the events in a block that happened in the
843// Auction Smart Contract.
844// To query by blockNum, set blockNum >= 0 and blockHash == nil.
845// To query by blockHash set blockHash != nil, and blockNum will be ignored.
846// If there are no events in that block the result is nil.
847func (c *AuctionClient) AuctionEventsByBlock(blockNum int64,
848	blockHash *ethCommon.Hash) (*AuctionEvents, error) {
849	var auctionEvents AuctionEvents
850
851	var blockNumBigInt *big.Int
852	if blockHash == nil {
853		blockNumBigInt = big.NewInt(blockNum)
854	}
855	query := ethereum.FilterQuery{
856		BlockHash: blockHash,
857		FromBlock: blockNumBigInt,
858		ToBlock:   blockNumBigInt,
859		Addresses: []ethCommon.Address{
860			c.address,
861		},
862		Topics: [][]ethCommon.Hash{},
863	}
864
865	logs, err := c.client.client.FilterLogs(context.TODO(), query)
866	if err != nil {
867		return nil, tracerr.Wrap(err)
868	}
869	if len(logs) == 0 {
870		return nil, nil
871	}
872
873	for _, vLog := range logs {
874		if blockHash != nil && vLog.BlockHash != *blockHash {
875			log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got",
876				vLog.BlockHash.String())
877			return nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
878		}
879		switch vLog.Topics[0] {
880		case logAuctionNewBid:
881			var auxNewBid struct {
882				Slot      *big.Int
883				BidAmount *big.Int
884				Address   ethCommon.Address
885			}
886			var newBid AuctionEventNewBid
887			if err := c.contractAbi.UnpackIntoInterface(&auxNewBid, "NewBid",
888				vLog.Data); err != nil {
889				return nil, tracerr.Wrap(err)
890			}
891			newBid.BidAmount = auxNewBid.BidAmount
892			newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
893			newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
894			auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
895		case logAuctionNewSlotDeadline:
896			var newSlotDeadline AuctionEventNewSlotDeadline
897			if err := c.contractAbi.UnpackIntoInterface(&newSlotDeadline,
898				"NewSlotDeadline", vLog.Data); err != nil {
899				return nil, tracerr.Wrap(err)
900			}
901			auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
902		case logAuctionNewClosedAuctionSlots:
903			var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
904			if err := c.contractAbi.UnpackIntoInterface(&newClosedAuctionSlots,
905				"NewClosedAuctionSlots", vLog.Data); err != nil {
906				return nil, tracerr.Wrap(err)
907			}
908			auctionEvents.NewClosedAuctionSlots =
909				append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
910		case logAuctionNewOutbidding:
911			var newOutbidding AuctionEventNewOutbidding
912			if err := c.contractAbi.UnpackIntoInterface(&newOutbidding, "NewOutbidding",
913				vLog.Data); err != nil {
914				return nil, tracerr.Wrap(err)
915			}
916			auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
917		case logAuctionNewDonationAddress:
918			var newDonationAddress AuctionEventNewDonationAddress
919			newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
920			auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress,
921				newDonationAddress)
922		case logAuctionNewBootCoordinator:
923			var newBootCoordinator AuctionEventNewBootCoordinator
924			if err := c.contractAbi.UnpackIntoInterface(&newBootCoordinator,
925				"NewBootCoordinator", vLog.Data); err != nil {
926				return nil, tracerr.Wrap(err)
927			}
928			newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
929			auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator,
930				newBootCoordinator)
931		case logAuctionNewOpenAuctionSlots:
932			var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
933			if err := c.contractAbi.UnpackIntoInterface(&newOpenAuctionSlots,
934				"NewOpenAuctionSlots", vLog.Data); err != nil {
935				return nil, tracerr.Wrap(err)
936			}
937			auctionEvents.NewOpenAuctionSlots =
938				append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
939		case logAuctionNewAllocationRatio:
940			var newAllocationRatio AuctionEventNewAllocationRatio
941			if err := c.contractAbi.UnpackIntoInterface(&newAllocationRatio,
942				"NewAllocationRatio", vLog.Data); err != nil {
943				return nil, tracerr.Wrap(err)
944			}
945			auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio,
946				newAllocationRatio)
947		case logAuctionSetCoordinator:
948			var setCoordinator AuctionEventSetCoordinator
949			if err := c.contractAbi.UnpackIntoInterface(&setCoordinator,
950				"SetCoordinator", vLog.Data); err != nil {
951				return nil, tracerr.Wrap(err)
952			}
953			setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
954			setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
955			auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
956		case logAuctionNewForgeAllocated:
957			var newForgeAllocated AuctionEventNewForgeAllocated
958			if err := c.contractAbi.UnpackIntoInterface(&newForgeAllocated,
959				"NewForgeAllocated", vLog.Data); err != nil {
960				return nil, tracerr.Wrap(err)
961			}
962			newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
963			newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
964			newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
965			auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated,
966				newForgeAllocated)
967		case logAuctionNewDefaultSlotSetBid:
968			var auxNewDefaultSlotSetBid struct {
969				SlotSet          *big.Int
970				NewInitialMinBid *big.Int
971			}
972			var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
973			if err := c.contractAbi.UnpackIntoInterface(&auxNewDefaultSlotSetBid,
974				"NewDefaultSlotSetBid", vLog.Data); err != nil {
975				return nil, tracerr.Wrap(err)
976			}
977			newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
978			newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
979			auctionEvents.NewDefaultSlotSetBid =
980				append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
981		case logAuctionNewForge:
982			var newForge AuctionEventNewForge
983			newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
984			newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
985			auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
986		case logAuctionHEZClaimed:
987			var HEZClaimed AuctionEventHEZClaimed
988			if err := c.contractAbi.UnpackIntoInterface(&HEZClaimed, "HEZClaimed",
989				vLog.Data); err != nil {
990				return nil, tracerr.Wrap(err)
991			}
992			HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
993			auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
994		}
995	}
996	return &auctionEvents, nil
997}