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, blockHash *ethCommon.Hash) (*AuctionEvents, 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	chainID     *big.Int
269	address     ethCommon.Address
270	tokenHEZCfg TokenConfig
271	auction     *HermezAuctionProtocol.HermezAuctionProtocol
272	tokenHEZ    *HEZ.HEZ
273	contractAbi abi.ABI
274	opts        *bind.CallOpts
275}
276
277// NewAuctionClient creates a new AuctionClient.  `tokenAddress` is the address of the HEZ tokens.
278func NewAuctionClient(client *EthereumClient, address ethCommon.Address, tokenHEZCfg TokenConfig) (*AuctionClient, error) {
279	contractAbi, err := abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI)))
280	if err != nil {
281		return nil, tracerr.Wrap(err)
282	}
283	auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(address, client.Client())
284	if err != nil {
285		return nil, tracerr.Wrap(err)
286	}
287	tokenHEZ, err := HEZ.NewHEZ(tokenHEZCfg.Address, client.Client())
288	if err != nil {
289		return nil, tracerr.Wrap(err)
290	}
291	chainID, err := client.EthChainID()
292	if err != nil {
293		return nil, tracerr.Wrap(err)
294	}
295	return &AuctionClient{
296		client:      client,
297		chainID:     chainID,
298		address:     address,
299		tokenHEZCfg: tokenHEZCfg,
300		auction:     auction,
301		tokenHEZ:    tokenHEZ,
302		contractAbi: contractAbi,
303		opts:        newCallOpts(),
304	}, nil
305}
306
307// AuctionSetSlotDeadline is the interface to call the smart contract function
308func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
309	var tx *types.Transaction
310	var err error
311	if tx, err = c.client.CallAuth(
312		0,
313		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
314			return c.auction.SetSlotDeadline(auth, newDeadline)
315		},
316	); err != nil {
317		return nil, tracerr.Wrap(fmt.Errorf("Failed setting slotDeadline: %w", err))
318	}
319	return tx, nil
320}
321
322// AuctionGetSlotDeadline is the interface to call the smart contract function
323func (c *AuctionClient) AuctionGetSlotDeadline() (slotDeadline uint8, err error) {
324	if err := c.client.Call(func(ec *ethclient.Client) error {
325		slotDeadline, err = c.auction.GetSlotDeadline(c.opts)
326		return tracerr.Wrap(err)
327	}); err != nil {
328		return 0, tracerr.Wrap(err)
329	}
330	return slotDeadline, nil
331}
332
333// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
334func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
335	if tx, err = c.client.CallAuth(
336		0,
337		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
338			return c.auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
339		},
340	); err != nil {
341		return nil, tracerr.Wrap(fmt.Errorf("Failed setting openAuctionSlots: %w", err))
342	}
343	return tx, nil
344}
345
346// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
347func (c *AuctionClient) AuctionGetOpenAuctionSlots() (openAuctionSlots uint16, err error) {
348	if err := c.client.Call(func(ec *ethclient.Client) error {
349		openAuctionSlots, err = c.auction.GetOpenAuctionSlots(c.opts)
350		return tracerr.Wrap(err)
351	}); err != nil {
352		return 0, tracerr.Wrap(err)
353	}
354	return openAuctionSlots, nil
355}
356
357// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
358func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
359	if tx, err = c.client.CallAuth(
360		0,
361		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
362			return c.auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
363		},
364	); err != nil {
365		return nil, tracerr.Wrap(fmt.Errorf("Failed setting closedAuctionSlots: %w", err))
366	}
367	return tx, nil
368}
369
370// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
371func (c *AuctionClient) AuctionGetClosedAuctionSlots() (closedAuctionSlots uint16, err error) {
372	if err := c.client.Call(func(ec *ethclient.Client) error {
373		closedAuctionSlots, err = c.auction.GetClosedAuctionSlots(c.opts)
374		return tracerr.Wrap(err)
375	}); err != nil {
376		return 0, tracerr.Wrap(err)
377	}
378	return closedAuctionSlots, nil
379}
380
381// AuctionSetOutbidding is the interface to call the smart contract function
382func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
383	if tx, err = c.client.CallAuth(
384		12500000, //nolint:gomnd
385		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
386			return c.auction.SetOutbidding(auth, newOutbidding)
387		},
388	); err != nil {
389		return nil, tracerr.Wrap(fmt.Errorf("Failed setting setOutbidding: %w", err))
390	}
391	return tx, nil
392}
393
394// AuctionGetOutbidding is the interface to call the smart contract function
395func (c *AuctionClient) AuctionGetOutbidding() (outbidding uint16, err error) {
396	if err := c.client.Call(func(ec *ethclient.Client) error {
397		outbidding, err = c.auction.GetOutbidding(c.opts)
398		return tracerr.Wrap(err)
399	}); err != nil {
400		return 0, tracerr.Wrap(err)
401	}
402	return outbidding, nil
403}
404
405// AuctionSetAllocationRatio is the interface to call the smart contract function
406func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
407	if tx, err = c.client.CallAuth(
408		0,
409		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
410			return c.auction.SetAllocationRatio(auth, newAllocationRatio)
411		},
412	); err != nil {
413		return nil, tracerr.Wrap(fmt.Errorf("Failed setting allocationRatio: %w", err))
414	}
415	return tx, nil
416}
417
418// AuctionGetAllocationRatio is the interface to call the smart contract function
419func (c *AuctionClient) AuctionGetAllocationRatio() (allocationRation [3]uint16, err error) {
420	if err := c.client.Call(func(ec *ethclient.Client) error {
421		allocationRation, err = c.auction.GetAllocationRatio(c.opts)
422		return tracerr.Wrap(err)
423	}); err != nil {
424		return [3]uint16{}, tracerr.Wrap(err)
425	}
426	return allocationRation, nil
427}
428
429// AuctionSetDonationAddress is the interface to call the smart contract function
430func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
431	if tx, err = c.client.CallAuth(
432		0,
433		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
434			return c.auction.SetDonationAddress(auth, newDonationAddress)
435		},
436	); err != nil {
437		return nil, tracerr.Wrap(fmt.Errorf("Failed setting donationAddress: %w", err))
438	}
439	return tx, nil
440}
441
442// AuctionGetDonationAddress is the interface to call the smart contract function
443func (c *AuctionClient) AuctionGetDonationAddress() (donationAddress *ethCommon.Address, err error) {
444	var _donationAddress ethCommon.Address
445	if err := c.client.Call(func(ec *ethclient.Client) error {
446		_donationAddress, err = c.auction.GetDonationAddress(c.opts)
447		return tracerr.Wrap(err)
448	}); err != nil {
449		return nil, tracerr.Wrap(err)
450	}
451	return &_donationAddress, nil
452}
453
454// AuctionSetBootCoordinator is the interface to call the smart contract function
455func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address, newBootCoordinatorURL string) (tx *types.Transaction, err error) {
456	if tx, err = c.client.CallAuth(
457		0,
458		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
459			return c.auction.SetBootCoordinator(auth, newBootCoordinator, newBootCoordinatorURL)
460		},
461	); err != nil {
462		return nil, tracerr.Wrap(fmt.Errorf("Failed setting bootCoordinator: %w", err))
463	}
464	return tx, nil
465}
466
467// AuctionGetBootCoordinator is the interface to call the smart contract function
468func (c *AuctionClient) AuctionGetBootCoordinator() (bootCoordinator *ethCommon.Address, err error) {
469	var _bootCoordinator ethCommon.Address
470	if err := c.client.Call(func(ec *ethclient.Client) error {
471		_bootCoordinator, err = c.auction.GetBootCoordinator(c.opts)
472		return tracerr.Wrap(err)
473	}); err != nil {
474		return nil, tracerr.Wrap(err)
475	}
476	return &_bootCoordinator, nil
477}
478
479// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
480func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
481	if tx, err = c.client.CallAuth(
482		0,
483		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
484			slotSetToSend := big.NewInt(slotSet)
485			return c.auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
486		},
487	); err != nil {
488		return nil, tracerr.Wrap(fmt.Errorf("Failed changing slotSet Bid: %w", err))
489	}
490	return tx, nil
491}
492
493// AuctionGetClaimableHEZ is the interface to call the smart contract function
494func (c *AuctionClient) AuctionGetClaimableHEZ(claimAddress ethCommon.Address) (claimableHEZ *big.Int, err error) {
495	if err := c.client.Call(func(ec *ethclient.Client) error {
496		claimableHEZ, err = c.auction.GetClaimableHEZ(c.opts, claimAddress)
497		return tracerr.Wrap(err)
498	}); err != nil {
499		return nil, tracerr.Wrap(err)
500	}
501	return claimableHEZ, nil
502}
503
504// AuctionSetCoordinator is the interface to call the smart contract function
505func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (tx *types.Transaction, err error) {
506	if tx, err = c.client.CallAuth(
507		0,
508		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
509			return c.auction.SetCoordinator(auth, forger, coordinatorURL)
510		},
511	); err != nil {
512		return nil, tracerr.Wrap(fmt.Errorf("Failed set coordinator: %w", err))
513	}
514	return tx, nil
515}
516
517// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
518func (c *AuctionClient) AuctionGetCurrentSlotNumber() (currentSlotNumber int64, err error) {
519	var _currentSlotNumber *big.Int
520	if err := c.client.Call(func(ec *ethclient.Client) error {
521		_currentSlotNumber, err = c.auction.GetCurrentSlotNumber(c.opts)
522		return tracerr.Wrap(err)
523	}); err != nil {
524		return 0, tracerr.Wrap(err)
525	}
526	return _currentSlotNumber.Int64(), nil
527}
528
529// AuctionGetMinBidBySlot is the interface to call the smart contract function
530func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (minBid *big.Int, err error) {
531	if err := c.client.Call(func(ec *ethclient.Client) error {
532		slotToSend := big.NewInt(slot)
533		minBid, err = c.auction.GetMinBidBySlot(c.opts, slotToSend)
534		return tracerr.Wrap(err)
535	}); err != nil {
536		return big.NewInt(0), tracerr.Wrap(err)
537	}
538	return minBid, nil
539}
540
541// AuctionGetSlotSet is the interface to call the smart contract function
542func (c *AuctionClient) AuctionGetSlotSet(slot int64) (slotSet *big.Int, err error) {
543	if err := c.client.Call(func(ec *ethclient.Client) error {
544		slotToSend := big.NewInt(slot)
545		slotSet, err = c.auction.GetSlotSet(c.opts, slotToSend)
546		return tracerr.Wrap(err)
547	}); err != nil {
548		return big.NewInt(0), tracerr.Wrap(err)
549	}
550	return slotSet, nil
551}
552
553// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
554func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (minBidSlotSet *big.Int, err error) {
555	if err := c.client.Call(func(ec *ethclient.Client) error {
556		minBidSlotSet, err = c.auction.GetDefaultSlotSetBid(c.opts, slotSet)
557		return tracerr.Wrap(err)
558	}); err != nil {
559		return big.NewInt(0), tracerr.Wrap(err)
560	}
561	return minBidSlotSet, nil
562}
563
564// AuctionGetSlotNumber is the interface to call the smart contract function
565func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (slot int64, err error) {
566	var _slot *big.Int
567	if err := c.client.Call(func(ec *ethclient.Client) error {
568		_slot, err = c.auction.GetSlotNumber(c.opts, big.NewInt(blockNum))
569		return tracerr.Wrap(err)
570	}); err != nil {
571		return 0, tracerr.Wrap(err)
572	}
573	return _slot.Int64(), nil
574}
575
576// AuctionBid is the interface to call the smart contract function
577func (c *AuctionClient) AuctionBid(amount *big.Int, slot int64, bidAmount *big.Int, deadline *big.Int) (tx *types.Transaction, err error) {
578	if tx, err = c.client.CallAuth(
579		0,
580		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
581			owner := c.client.account.Address
582			spender := c.address
583			nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
584			if err != nil {
585				return nil, tracerr.Wrap(err)
586			}
587			tokenName := c.tokenHEZCfg.Name
588			tokenAddr := c.tokenHEZCfg.Address
589			digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID, amount, nonce, deadline, tokenName)
590			signature, _ := c.client.ks.SignHash(*c.client.account, digest)
591			permit := createPermit(owner, spender, amount, deadline, digest, signature)
592			_slot := big.NewInt(slot)
593			return c.auction.ProcessBid(auth, amount, _slot, bidAmount, permit)
594		},
595	); err != nil {
596		return nil, tracerr.Wrap(fmt.Errorf("Failed bid: %w", err))
597	}
598	return tx, nil
599}
600
601// AuctionMultiBid is the interface to call the smart contract function
602func (c *AuctionClient) AuctionMultiBid(amount *big.Int, startingSlot, endingSlot int64, slotSets [6]bool,
603	maxBid, minBid, deadline *big.Int) (tx *types.Transaction, err error) {
604	if tx, err = c.client.CallAuth(
605		1000000, //nolint:gomnd
606		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
607			owner := c.client.account.Address
608			spender := c.address
609			nonce, err := c.tokenHEZ.Nonces(c.opts, owner)
610			if err != nil {
611				return nil, tracerr.Wrap(err)
612			}
613			tokenName := c.tokenHEZCfg.Name
614			tokenAddr := c.tokenHEZCfg.Address
615
616			digest, _ := createPermitDigest(tokenAddr, owner, spender, c.chainID, amount, nonce, deadline, tokenName)
617			signature, _ := c.client.ks.SignHash(*c.client.account, digest)
618			permit := createPermit(owner, spender, amount, deadline, digest, signature)
619			_startingSlot := big.NewInt(startingSlot)
620			_endingSlot := big.NewInt(endingSlot)
621			return c.auction.ProcessMultiBid(auth, amount, _startingSlot, _endingSlot, slotSets, maxBid, minBid, permit)
622		},
623	); err != nil {
624		return nil, tracerr.Wrap(fmt.Errorf("Failed multibid: %w", err))
625	}
626	return tx, nil
627}
628
629// AuctionCanForge is the interface to call the smart contract function
630func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (canForge bool, err error) {
631	if err := c.client.Call(func(ec *ethclient.Client) error {
632		canForge, err = c.auction.CanForge(c.opts, forger, big.NewInt(blockNum))
633		return tracerr.Wrap(err)
634	}); err != nil {
635		return false, tracerr.Wrap(err)
636	}
637	return canForge, nil
638}
639
640// AuctionClaimHEZ is the interface to call the smart contract function
641func (c *AuctionClient) AuctionClaimHEZ() (tx *types.Transaction, err error) {
642	if tx, err = c.client.CallAuth(
643		0,
644		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
645			return c.auction.ClaimHEZ(auth)
646		},
647	); err != nil {
648		return nil, tracerr.Wrap(fmt.Errorf("Failed claim HEZ: %w", err))
649	}
650	return tx, nil
651}
652
653// AuctionForge is the interface to call the smart contract function
654func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
655	if tx, err = c.client.CallAuth(
656		0,
657		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
658			return c.auction.Forge(auth, forger)
659		},
660	); err != nil {
661		return nil, tracerr.Wrap(fmt.Errorf("Failed forge: %w", err))
662	}
663	return tx, nil
664}
665
666// AuctionConstants returns the Constants of the Auction Smart Contract
667func (c *AuctionClient) AuctionConstants() (auctionConstants *common.AuctionConstants, err error) {
668	auctionConstants = new(common.AuctionConstants)
669	if err := c.client.Call(func(ec *ethclient.Client) error {
670		auctionConstants.BlocksPerSlot, err = c.auction.BLOCKSPERSLOT(c.opts)
671		if err != nil {
672			return tracerr.Wrap(err)
673		}
674		genesisBlock, err := c.auction.GenesisBlock(c.opts)
675		if err != nil {
676			return tracerr.Wrap(err)
677		}
678		auctionConstants.GenesisBlockNum = genesisBlock.Int64()
679		auctionConstants.HermezRollup, err = c.auction.HermezRollup(c.opts)
680		if err != nil {
681			return tracerr.Wrap(err)
682		}
683		auctionConstants.InitialMinimalBidding, err = c.auction.INITIALMINIMALBIDDING(c.opts)
684		if err != nil {
685			return tracerr.Wrap(err)
686		}
687		auctionConstants.GovernanceAddress, err = c.auction.GovernanceAddress(c.opts)
688		if err != nil {
689			return tracerr.Wrap(err)
690		}
691		auctionConstants.TokenHEZ, err = c.auction.TokenHEZ(c.opts)
692		if err != nil {
693			return tracerr.Wrap(err)
694		}
695		return nil
696	}); err != nil {
697		return nil, tracerr.Wrap(err)
698	}
699	return auctionConstants, nil
700}
701
702// AuctionVariables returns the variables of the Auction Smart Contract
703func (c *AuctionClient) AuctionVariables() (auctionVariables *common.AuctionVariables, err error) {
704	auctionVariables = new(common.AuctionVariables)
705	if err := c.client.Call(func(ec *ethclient.Client) error {
706		auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
707		if err != nil {
708			return tracerr.Wrap(err)
709		}
710		bootCoordinator, err := c.AuctionGetBootCoordinator()
711		if err != nil {
712			return tracerr.Wrap(err)
713		}
714		auctionVariables.BootCoordinator = *bootCoordinator
715		auctionVariables.BootCoordinatorURL, err = c.auction.BootCoordinatorURL(c.opts)
716		if err != nil {
717			return tracerr.Wrap(err)
718		}
719		auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
720		if err != nil {
721			return tracerr.Wrap(err)
722		}
723		var defaultSlotSetBid [6]*big.Int
724		for i := uint8(0); i < 6; i++ {
725			bid, err := c.AuctionGetDefaultSlotSetBid(i)
726			if err != nil {
727				return tracerr.Wrap(err)
728			}
729			defaultSlotSetBid[i] = bid
730		}
731		auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
732		donationAddress, err := c.AuctionGetDonationAddress()
733		if err != nil {
734			return tracerr.Wrap(err)
735		}
736		auctionVariables.DonationAddress = *donationAddress
737		auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
738		if err != nil {
739			return tracerr.Wrap(err)
740		}
741		auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
742		if err != nil {
743			return tracerr.Wrap(err)
744		}
745		auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
746		return tracerr.Wrap(err)
747	}); err != nil {
748		return nil, tracerr.Wrap(err)
749	}
750	return auctionVariables, nil
751}
752
753var (
754	logAuctionNewBid                = crypto.Keccak256Hash([]byte("NewBid(uint128,uint128,address)"))
755	logAuctionNewSlotDeadline       = crypto.Keccak256Hash([]byte("NewSlotDeadline(uint8)"))
756	logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte("NewClosedAuctionSlots(uint16)"))
757	logAuctionNewOutbidding         = crypto.Keccak256Hash([]byte("NewOutbidding(uint16)"))
758	logAuctionNewDonationAddress    = crypto.Keccak256Hash([]byte("NewDonationAddress(address)"))
759	logAuctionNewBootCoordinator    = crypto.Keccak256Hash([]byte("NewBootCoordinator(address,string)"))
760	logAuctionNewOpenAuctionSlots   = crypto.Keccak256Hash([]byte("NewOpenAuctionSlots(uint16)"))
761	logAuctionNewAllocationRatio    = crypto.Keccak256Hash([]byte("NewAllocationRatio(uint16[3])"))
762	logAuctionSetCoordinator        = crypto.Keccak256Hash([]byte("SetCoordinator(address,address,string)"))
763	logAuctionNewForgeAllocated     = crypto.Keccak256Hash([]byte("NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
764	logAuctionNewDefaultSlotSetBid  = crypto.Keccak256Hash([]byte("NewDefaultSlotSetBid(uint128,uint128)"))
765	logAuctionNewForge              = crypto.Keccak256Hash([]byte("NewForge(address,uint128)"))
766	logAuctionHEZClaimed            = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)"))
767	logAuctionInitialize            = crypto.Keccak256Hash([]byte(
768		"InitializeHermezAuctionProtocolEvent(address,address,string,uint16,uint8,uint16,uint16,uint16[3])"))
769)
770
771// AuctionEventInit returns the initialize event with its corresponding block number
772func (c *AuctionClient) AuctionEventInit() (*AuctionEventInitialize, int64, error) {
773	query := ethereum.FilterQuery{
774		Addresses: []ethCommon.Address{
775			c.address,
776		},
777		Topics: [][]ethCommon.Hash{{logAuctionInitialize}},
778	}
779	logs, err := c.client.client.FilterLogs(context.Background(), query)
780	if err != nil {
781		return nil, 0, tracerr.Wrap(err)
782	}
783	if len(logs) != 1 {
784		return nil, 0, tracerr.Wrap(fmt.Errorf("no event of type InitializeHermezAuctionProtocolEvent found"))
785	}
786	vLog := logs[0]
787	if vLog.Topics[0] != logAuctionInitialize {
788		return nil, 0, tracerr.Wrap(fmt.Errorf("event is not InitializeHermezAuctionProtocolEvent"))
789	}
790
791	var auctionInit AuctionEventInitialize
792	if err := c.contractAbi.UnpackIntoInterface(&auctionInit,
793		"InitializeHermezAuctionProtocolEvent", vLog.Data); err != nil {
794		return nil, 0, tracerr.Wrap(err)
795	}
796	return &auctionInit, int64(vLog.BlockNumber), tracerr.Wrap(err)
797}
798
799// AuctionEventsByBlock returns the events in a block that happened in the
800// Auction Smart Contract.
801// To query by blockNum, set blockNum >= 0 and blockHash == nil.
802// To query by blockHash, set blockNum == -1 and blockHash != nil.
803// If there are no events in that block the result is nil.
804func (c *AuctionClient) AuctionEventsByBlock(blockNum int64,
805	blockHash *ethCommon.Hash) (*AuctionEvents, error) {
806	var auctionEvents AuctionEvents
807
808	var blockNumBigInt *big.Int
809	if blockNum >= 0 {
810		blockNumBigInt = big.NewInt(blockNum)
811	}
812	query := ethereum.FilterQuery{
813		BlockHash: blockHash,
814		FromBlock: blockNumBigInt,
815		ToBlock:   blockNumBigInt,
816		Addresses: []ethCommon.Address{
817			c.address,
818		},
819		Topics: [][]ethCommon.Hash{},
820	}
821
822	logs, err := c.client.client.FilterLogs(context.TODO(), query)
823	if err != nil {
824		return nil, tracerr.Wrap(err)
825	}
826	if len(logs) == 0 {
827		return nil, nil
828	}
829
830	for _, vLog := range logs {
831		if blockHash != nil && vLog.BlockHash != *blockHash {
832			log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
833			return nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
834		}
835		switch vLog.Topics[0] {
836		case logAuctionNewBid:
837			var auxNewBid struct {
838				Slot      *big.Int
839				BidAmount *big.Int
840				Address   ethCommon.Address
841			}
842			var newBid AuctionEventNewBid
843			if err := c.contractAbi.UnpackIntoInterface(&auxNewBid, "NewBid", vLog.Data); err != nil {
844				return nil, tracerr.Wrap(err)
845			}
846			newBid.BidAmount = auxNewBid.BidAmount
847			newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
848			newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
849			auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
850		case logAuctionNewSlotDeadline:
851			var newSlotDeadline AuctionEventNewSlotDeadline
852			if err := c.contractAbi.UnpackIntoInterface(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
853				return nil, tracerr.Wrap(err)
854			}
855			auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
856		case logAuctionNewClosedAuctionSlots:
857			var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
858			if err := c.contractAbi.UnpackIntoInterface(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
859				return nil, tracerr.Wrap(err)
860			}
861			auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
862		case logAuctionNewOutbidding:
863			var newOutbidding AuctionEventNewOutbidding
864			if err := c.contractAbi.UnpackIntoInterface(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
865				return nil, tracerr.Wrap(err)
866			}
867			auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
868		case logAuctionNewDonationAddress:
869			var newDonationAddress AuctionEventNewDonationAddress
870			newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
871			auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
872		case logAuctionNewBootCoordinator:
873			var newBootCoordinator AuctionEventNewBootCoordinator
874			if err := c.contractAbi.UnpackIntoInterface(&newBootCoordinator, "NewBootCoordinator", vLog.Data); err != nil {
875				return nil, tracerr.Wrap(err)
876			}
877			newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
878			auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
879		case logAuctionNewOpenAuctionSlots:
880			var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
881			if err := c.contractAbi.UnpackIntoInterface(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
882				return nil, tracerr.Wrap(err)
883			}
884			auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
885		case logAuctionNewAllocationRatio:
886			var newAllocationRatio AuctionEventNewAllocationRatio
887			if err := c.contractAbi.UnpackIntoInterface(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
888				return nil, tracerr.Wrap(err)
889			}
890			auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
891		case logAuctionSetCoordinator:
892			var setCoordinator AuctionEventSetCoordinator
893			if err := c.contractAbi.UnpackIntoInterface(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
894				return nil, tracerr.Wrap(err)
895			}
896			setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
897			setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
898			auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
899		case logAuctionNewForgeAllocated:
900			var newForgeAllocated AuctionEventNewForgeAllocated
901			if err := c.contractAbi.UnpackIntoInterface(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
902				return nil, tracerr.Wrap(err)
903			}
904			newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
905			newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
906			newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
907			auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
908		case logAuctionNewDefaultSlotSetBid:
909			var auxNewDefaultSlotSetBid struct {
910				SlotSet          *big.Int
911				NewInitialMinBid *big.Int
912			}
913			var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
914			if err := c.contractAbi.UnpackIntoInterface(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
915				return nil, tracerr.Wrap(err)
916			}
917			newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
918			newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
919			auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
920		case logAuctionNewForge:
921			var newForge AuctionEventNewForge
922			newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
923			newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
924			auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
925		case logAuctionHEZClaimed:
926			var HEZClaimed AuctionEventHEZClaimed
927			if err := c.contractAbi.UnpackIntoInterface(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
928				return nil, tracerr.Wrap(err)
929			}
930			HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
931			auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
932		}
933	}
934	return &auctionEvents, nil
935}