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