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