arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/eth/auction.go
eth/auction.goRaw
  1package eth
  2
  3import (
  4	"context"
  5	"encoding/binary"
  6	"fmt"
  7	"math/big"
  8	"strings"
  9
 10	"github.com/ethereum/go-ethereum"
 11	"github.com/ethereum/go-ethereum/accounts/abi"
 12	"github.com/ethereum/go-ethereum/accounts/abi/bind"
 13	ethCommon "github.com/ethereum/go-ethereum/common"
 14	"github.com/ethereum/go-ethereum/core/types"
 15	"github.com/ethereum/go-ethereum/crypto"
 16	"github.com/ethereum/go-ethereum/ethclient"
 17	HermezAuctionProtocol "github.com/hermeznetwork/hermez-node/eth/contracts/auction"
 18	ERC777 "github.com/hermeznetwork/hermez-node/eth/contracts/erc777"
 19	"golang.org/x/crypto/sha3"
 20)
 21
 22// AuctionConstants are the constants of the Rollup Smart Contract
 23type AuctionConstants struct {
 24	// Blocks per slot
 25	BlocksPerSlot uint8
 26	// Minimum bid when no one has bid yet
 27	InitialMinimalBidding *big.Int
 28	// First block where the first slot begins
 29	GenesisBlockNum int64
 30	// ERC777 token with which the bids will be made
 31	TokenHEZ ethCommon.Address
 32	// HermezRollup smartcontract address
 33	HermezRollup ethCommon.Address
 34	// Hermez Governanze Token smartcontract address who controls some parameters and collects HEZ fee
 35	// Only for test
 36	GovernanceAddress ethCommon.Address
 37}
 38
 39// SlotState is the state of a slot
 40type SlotState struct {
 41	Bidder       ethCommon.Address
 42	Fulfilled    bool
 43	BidAmount    *big.Int
 44	ClosedMinBid *big.Int
 45}
 46
 47// NewSlotState returns an empty SlotState
 48func NewSlotState() *SlotState {
 49	return &SlotState{
 50		Bidder:       ethCommon.Address{},
 51		Fulfilled:    false,
 52		BidAmount:    big.NewInt(0),
 53		ClosedMinBid: big.NewInt(0),
 54	}
 55}
 56
 57// Coordinator is the details of the Coordinator identified by the forger address
 58type Coordinator struct {
 59	Forger ethCommon.Address
 60	URL    string
 61}
 62
 63// AuctionVariables are the variables of the Auction Smart Contract
 64type AuctionVariables struct {
 65	// Boot Coordinator Address
 66	DonationAddress ethCommon.Address
 67	// Boot Coordinator Address
 68	BootCoordinator ethCommon.Address
 69	// The minimum bid value in a series of 6 slots
 70	DefaultSlotSetBid [6]*big.Int
 71	// Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
 72	ClosedAuctionSlots uint16
 73	// Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
 74	OpenAuctionSlots uint16
 75	// How the HEZ tokens deposited by the slot winner are distributed (Burn: 40% - Donation: 40% - HGT: 20%)
 76	AllocationRatio [3]uint16
 77	// Minimum outbid (percentage) over the previous one to consider it valid
 78	Outbidding uint16
 79	// Number of blocks at the end of a slot in which any coordinator can forge if the winner has not forged one before
 80	SlotDeadline uint8
 81}
 82
 83// AuctionState represents the state of the Rollup in the Smart Contract
 84type AuctionState struct {
 85	// Mapping to control slot state
 86	Slots map[int64]*SlotState
 87	// Mapping to control balances pending to claim
 88	PendingBalances map[ethCommon.Address]*big.Int
 89	// Mapping to register all the coordinators. The address used for the mapping is the forger address
 90	Coordinators map[ethCommon.Address]*Coordinator
 91}
 92
 93// AuctionEventNewBid is an event of the Auction Smart Contract
 94type AuctionEventNewBid struct {
 95	Slot      int64
 96	BidAmount *big.Int
 97	Bidder    ethCommon.Address
 98}
 99
100// AuctionEventNewSlotDeadline is an event of the Auction Smart Contract
101type AuctionEventNewSlotDeadline struct {
102	NewSlotDeadline uint8
103}
104
105// AuctionEventNewClosedAuctionSlots is an event of the Auction Smart Contract
106type AuctionEventNewClosedAuctionSlots struct {
107	NewClosedAuctionSlots uint16
108}
109
110// AuctionEventNewOutbidding is an event of the Auction Smart Contract
111type AuctionEventNewOutbidding struct {
112	NewOutbidding uint16
113}
114
115// AuctionEventNewDonationAddress is an event of the Auction Smart Contract
116type AuctionEventNewDonationAddress struct {
117	NewDonationAddress ethCommon.Address
118}
119
120// AuctionEventNewBootCoordinator is an event of the Auction Smart Contract
121type AuctionEventNewBootCoordinator struct {
122	NewBootCoordinator ethCommon.Address
123}
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) (*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(slot int64, bidAmount *big.Int) (*types.Transaction, error)
241	AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int) (*types.Transaction, error)
242
243	// Forge
244	AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error)
245	AuctionForge(forger ethCommon.Address) (*types.Transaction, error)
246
247	// Fees
248	AuctionClaimHEZ() (*types.Transaction, error)
249	AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error)
250
251	//
252	// Smart Contract Status
253	//
254
255	AuctionConstants() (*AuctionConstants, error)
256	AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error)
257}
258
259//
260// Implementation
261//
262
263// AuctionClient is the implementation of the interface to the Auction Smart Contract in ethereum.
264type AuctionClient struct {
265	client       *EthereumClient
266	address      ethCommon.Address
267	tokenAddress ethCommon.Address
268	auction      *HermezAuctionProtocol.HermezAuctionProtocol
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, tokenAddress ethCommon.Address) (*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	return &AuctionClient{
283		client:       client,
284		address:      address,
285		tokenAddress: tokenAddress,
286		auction:      auction,
287		contractAbi:  contractAbi,
288	}, nil
289}
290
291// AuctionSetSlotDeadline is the interface to call the smart contract function
292func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
293	var tx *types.Transaction
294	var err error
295	if tx, err = c.client.CallAuth(
296		0,
297		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
298			return c.auction.SetSlotDeadline(auth, newDeadline)
299		},
300	); err != nil {
301		return nil, fmt.Errorf("Failed setting slotDeadline: %w", err)
302	}
303	return tx, nil
304}
305
306// AuctionGetSlotDeadline is the interface to call the smart contract function
307func (c *AuctionClient) AuctionGetSlotDeadline() (slotDeadline uint8, err error) {
308	if err := c.client.Call(func(ec *ethclient.Client) error {
309		slotDeadline, err = c.auction.GetSlotDeadline(nil)
310		return err
311	}); err != nil {
312		return 0, err
313	}
314	return slotDeadline, nil
315}
316
317// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
318func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (tx *types.Transaction, err error) {
319	if tx, err = c.client.CallAuth(
320		0,
321		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
322			return c.auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
323		},
324	); err != nil {
325		return nil, fmt.Errorf("Failed setting openAuctionSlots: %w", err)
326	}
327	return tx, nil
328}
329
330// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
331func (c *AuctionClient) AuctionGetOpenAuctionSlots() (openAuctionSlots uint16, err error) {
332	if err := c.client.Call(func(ec *ethclient.Client) error {
333		openAuctionSlots, err = c.auction.GetOpenAuctionSlots(nil)
334		return err
335	}); err != nil {
336		return 0, err
337	}
338	return openAuctionSlots, nil
339}
340
341// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
342func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (tx *types.Transaction, err error) {
343	if tx, err = c.client.CallAuth(
344		0,
345		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
346			return c.auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
347		},
348	); err != nil {
349		return nil, fmt.Errorf("Failed setting closedAuctionSlots: %w", err)
350	}
351	return tx, nil
352}
353
354// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
355func (c *AuctionClient) AuctionGetClosedAuctionSlots() (closedAuctionSlots uint16, err error) {
356	if err := c.client.Call(func(ec *ethclient.Client) error {
357		closedAuctionSlots, err = c.auction.GetClosedAuctionSlots(nil)
358		return err
359	}); err != nil {
360		return 0, err
361	}
362	return closedAuctionSlots, nil
363}
364
365// AuctionSetOutbidding is the interface to call the smart contract function
366func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (tx *types.Transaction, err error) {
367	if tx, err = c.client.CallAuth(
368		12500000, //nolint:gomnd
369		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
370			return c.auction.SetOutbidding(auth, newOutbidding)
371		},
372	); err != nil {
373		return nil, fmt.Errorf("Failed setting setOutbidding: %w", err)
374	}
375	return tx, nil
376}
377
378// AuctionGetOutbidding is the interface to call the smart contract function
379func (c *AuctionClient) AuctionGetOutbidding() (outbidding uint16, err error) {
380	if err := c.client.Call(func(ec *ethclient.Client) error {
381		outbidding, err = c.auction.GetOutbidding(nil)
382		return err
383	}); err != nil {
384		return 0, err
385	}
386	return outbidding, nil
387}
388
389// AuctionSetAllocationRatio is the interface to call the smart contract function
390func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (tx *types.Transaction, err error) {
391	if tx, err = c.client.CallAuth(
392		0,
393		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
394			return c.auction.SetAllocationRatio(auth, newAllocationRatio)
395		},
396	); err != nil {
397		return nil, fmt.Errorf("Failed setting allocationRatio: %w", err)
398	}
399	return tx, nil
400}
401
402// AuctionGetAllocationRatio is the interface to call the smart contract function
403func (c *AuctionClient) AuctionGetAllocationRatio() (allocationRation [3]uint16, err error) {
404	if err := c.client.Call(func(ec *ethclient.Client) error {
405		allocationRation, err = c.auction.GetAllocationRatio(nil)
406		return err
407	}); err != nil {
408		return [3]uint16{}, err
409	}
410	return allocationRation, nil
411}
412
413// AuctionSetDonationAddress is the interface to call the smart contract function
414func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (tx *types.Transaction, err error) {
415	if tx, err = c.client.CallAuth(
416		0,
417		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
418			return c.auction.SetDonationAddress(auth, newDonationAddress)
419		},
420	); err != nil {
421		return nil, fmt.Errorf("Failed setting donationAddress: %w", err)
422	}
423	return tx, nil
424}
425
426// AuctionGetDonationAddress is the interface to call the smart contract function
427func (c *AuctionClient) AuctionGetDonationAddress() (donationAddress *ethCommon.Address, err error) {
428	var _donationAddress ethCommon.Address
429	if err := c.client.Call(func(ec *ethclient.Client) error {
430		_donationAddress, err = c.auction.GetDonationAddress(nil)
431		return err
432	}); err != nil {
433		return nil, err
434	}
435	return &_donationAddress, nil
436}
437
438// AuctionSetBootCoordinator is the interface to call the smart contract function
439func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (tx *types.Transaction, err error) {
440	if tx, err = c.client.CallAuth(
441		0,
442		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
443			return c.auction.SetBootCoordinator(auth, newBootCoordinator)
444		},
445	); err != nil {
446		return nil, fmt.Errorf("Failed setting bootCoordinator: %w", err)
447	}
448	return tx, nil
449}
450
451// AuctionGetBootCoordinator is the interface to call the smart contract function
452func (c *AuctionClient) AuctionGetBootCoordinator() (bootCoordinator *ethCommon.Address, err error) {
453	var _bootCoordinator ethCommon.Address
454	if err := c.client.Call(func(ec *ethclient.Client) error {
455		_bootCoordinator, err = c.auction.GetBootCoordinator(nil)
456		return err
457	}); err != nil {
458		return nil, err
459	}
460	return &_bootCoordinator, nil
461}
462
463// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
464func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (tx *types.Transaction, err error) {
465	if tx, err = c.client.CallAuth(
466		0,
467		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
468			slotSetToSend := big.NewInt(slotSet)
469			return c.auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
470		},
471	); err != nil {
472		return nil, fmt.Errorf("Failed changing slotSet Bid: %w", err)
473	}
474	return tx, nil
475}
476
477// AuctionGetClaimableHEZ is the interface to call the smart contract function
478func (c *AuctionClient) AuctionGetClaimableHEZ(claimAddress ethCommon.Address) (claimableHEZ *big.Int, err error) {
479	if err := c.client.Call(func(ec *ethclient.Client) error {
480		claimableHEZ, err = c.auction.GetClaimableHEZ(nil, claimAddress)
481		return err
482	}); err != nil {
483		return nil, err
484	}
485	return claimableHEZ, nil
486}
487
488// AuctionSetCoordinator is the interface to call the smart contract function
489func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (tx *types.Transaction, err error) {
490	if tx, err = c.client.CallAuth(
491		0,
492		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
493			return c.auction.SetCoordinator(auth, forger, coordinatorURL)
494		},
495	); err != nil {
496		return nil, fmt.Errorf("Failed set coordinator: %w", err)
497	}
498	return tx, nil
499}
500
501// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
502func (c *AuctionClient) AuctionGetCurrentSlotNumber() (currentSlotNumber int64, err error) {
503	var _currentSlotNumber *big.Int
504	if err := c.client.Call(func(ec *ethclient.Client) error {
505		_currentSlotNumber, err = c.auction.GetCurrentSlotNumber(nil)
506		return err
507	}); err != nil {
508		return 0, err
509	}
510	return _currentSlotNumber.Int64(), nil
511}
512
513// AuctionGetMinBidBySlot is the interface to call the smart contract function
514func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (minBid *big.Int, err error) {
515	if err := c.client.Call(func(ec *ethclient.Client) error {
516		slotToSend := big.NewInt(slot)
517		minBid, err = c.auction.GetMinBidBySlot(nil, slotToSend)
518		return err
519	}); err != nil {
520		return big.NewInt(0), err
521	}
522	return minBid, nil
523}
524
525// AuctionGetSlotSet is the interface to call the smart contract function
526func (c *AuctionClient) AuctionGetSlotSet(slot int64) (slotSet *big.Int, err error) {
527	if err := c.client.Call(func(ec *ethclient.Client) error {
528		slotToSend := big.NewInt(slot)
529		slotSet, err = c.auction.GetSlotSet(nil, slotToSend)
530		return err
531	}); err != nil {
532		return big.NewInt(0), err
533	}
534	return slotSet, nil
535}
536
537// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
538func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (minBidSlotSet *big.Int, err error) {
539	if err := c.client.Call(func(ec *ethclient.Client) error {
540		minBidSlotSet, err = c.auction.GetDefaultSlotSetBid(nil, slotSet)
541		return err
542	}); err != nil {
543		return big.NewInt(0), err
544	}
545	return minBidSlotSet, nil
546}
547
548// AuctionGetSlotNumber is the interface to call the smart contract function
549func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (slot int64, err error) {
550	var _slot *big.Int
551	if err := c.client.Call(func(ec *ethclient.Client) error {
552		_slot, err = c.auction.GetSlotNumber(nil, big.NewInt(blockNum))
553		return err
554	}); err != nil {
555		return 0, err
556	}
557	return _slot.Int64(), nil
558}
559
560// AuctionBid is the interface to call the smart contract function
561func (c *AuctionClient) AuctionBid(slot int64, bidAmount *big.Int) (tx *types.Transaction, err error) {
562	if tx, err = c.client.CallAuth(
563		0,
564		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
565			tokens, err := ERC777.NewERC777(c.tokenAddress, ec)
566			if err != nil {
567				return nil, err
568			}
569			bidFnSignature := []byte("bid(uint128,uint128)")
570			hash := sha3.NewLegacyKeccak256()
571			_, err = hash.Write(bidFnSignature)
572			if err != nil {
573				return nil, err
574			}
575			methodID := hash.Sum(nil)[:4]
576			slotBytes := make([]byte, 8)
577			binary.BigEndian.PutUint64(slotBytes, uint64(slot))
578			paddedSlot := ethCommon.LeftPadBytes(slotBytes, 32)
579			paddedAmount := ethCommon.LeftPadBytes(bidAmount.Bytes(), 32)
580			var userData []byte
581			userData = append(userData, methodID...)
582			userData = append(userData, paddedSlot...)
583			userData = append(userData, paddedAmount...)
584			return tokens.Send(auth, c.address, bidAmount, userData)
585		},
586	); err != nil {
587		return nil, fmt.Errorf("Failed bid: %w", err)
588	}
589	return tx, nil
590}
591
592// AuctionMultiBid is the interface to call the smart contract function
593func (c *AuctionClient) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool,
594	maxBid, closedMinBid, budget *big.Int) (tx *types.Transaction, err error) {
595	if tx, err = c.client.CallAuth(
596		1000000, //nolint:gomnd
597		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
598			tokens, err := ERC777.NewERC777(c.tokenAddress, ec)
599			if err != nil {
600				return nil, err
601			}
602			multiBidFnSignature := []byte("multiBid(uint128,uint128,bool[6],uint128,uint128)")
603			hash := sha3.NewLegacyKeccak256()
604			_, err = hash.Write(multiBidFnSignature)
605			if err != nil {
606				return nil, err
607			}
608			methodID := hash.Sum(nil)[:4]
609			startingSlotBytes := make([]byte, 8)
610			binary.BigEndian.PutUint64(startingSlotBytes, uint64(startingSlot))
611			paddedStartingSlot := ethCommon.LeftPadBytes(startingSlotBytes, 32)
612			endingSlotBytes := make([]byte, 8)
613			binary.BigEndian.PutUint64(endingSlotBytes, uint64(endingSlot))
614			paddedEndingSlot := ethCommon.LeftPadBytes(endingSlotBytes, 32)
615			paddedMinBid := ethCommon.LeftPadBytes(closedMinBid.Bytes(), 32)
616			paddedMaxBid := ethCommon.LeftPadBytes(maxBid.Bytes(), 32)
617			var userData []byte
618			userData = append(userData, methodID...)
619			userData = append(userData, paddedStartingSlot...)
620			userData = append(userData, paddedEndingSlot...)
621			for i := 0; i < len(slotSet); i++ {
622				if slotSet[i] {
623					paddedSlotSet := ethCommon.LeftPadBytes([]byte{1}, 32)
624					userData = append(userData, paddedSlotSet...)
625				} else {
626					paddedSlotSet := ethCommon.LeftPadBytes([]byte{0}, 32)
627					userData = append(userData, paddedSlotSet...)
628				}
629			}
630			userData = append(userData, paddedMaxBid...)
631			userData = append(userData, paddedMinBid...)
632			return tokens.Send(auth, c.address, budget, userData)
633		},
634	); err != nil {
635		return nil, fmt.Errorf("Failed multibid: %w", err)
636	}
637	return tx, nil
638}
639
640// AuctionCanForge is the interface to call the smart contract function
641func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (canForge bool, err error) {
642	if err := c.client.Call(func(ec *ethclient.Client) error {
643		canForge, err = c.auction.CanForge(nil, forger, big.NewInt(blockNum))
644		return err
645	}); err != nil {
646		return false, err
647	}
648	return canForge, nil
649}
650
651// AuctionClaimHEZ is the interface to call the smart contract function
652func (c *AuctionClient) AuctionClaimHEZ() (tx *types.Transaction, err error) {
653	if tx, err = c.client.CallAuth(
654		0,
655		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
656			return c.auction.ClaimHEZ(auth)
657		},
658	); err != nil {
659		return nil, fmt.Errorf("Failed claim HEZ: %w", err)
660	}
661	return tx, nil
662}
663
664// AuctionForge is the interface to call the smart contract function
665func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (tx *types.Transaction, err error) {
666	if tx, err = c.client.CallAuth(
667		0,
668		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
669			return c.auction.Forge(auth, forger)
670		},
671	); err != nil {
672		return nil, fmt.Errorf("Failed forge: %w", err)
673	}
674	return tx, nil
675}
676
677// AuctionConstants returns the Constants of the Auction Smart Contract
678func (c *AuctionClient) AuctionConstants() (auctionConstants *AuctionConstants, err error) {
679	auctionConstants = new(AuctionConstants)
680	if err := c.client.Call(func(ec *ethclient.Client) error {
681		auctionConstants.BlocksPerSlot, err = c.auction.BLOCKSPERSLOT(nil)
682		if err != nil {
683			return err
684		}
685		genesisBlock, err := c.auction.GenesisBlock(nil)
686		if err != nil {
687			return err
688		}
689		auctionConstants.GenesisBlockNum = genesisBlock.Int64()
690		auctionConstants.HermezRollup, err = c.auction.HermezRollup(nil)
691		if err != nil {
692			return err
693		}
694		auctionConstants.InitialMinimalBidding, err = c.auction.INITIALMINIMALBIDDING(nil)
695		if err != nil {
696			return err
697		}
698		auctionConstants.TokenHEZ, err = c.auction.TokenHEZ(nil)
699		return err
700	}); err != nil {
701		return nil, err
702	}
703	return auctionConstants, nil
704}
705
706// AuctionVariables returns the variables of the Auction Smart Contract
707func (c *AuctionClient) AuctionVariables() (auctionVariables *AuctionVariables, err error) {
708	auctionVariables = new(AuctionVariables)
709	if err := c.client.Call(func(ec *ethclient.Client) error {
710		auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
711		if err != nil {
712			return err
713		}
714		bootCoordinator, err := c.AuctionGetBootCoordinator()
715		if err != nil {
716			return err
717		}
718		auctionVariables.BootCoordinator = *bootCoordinator
719		auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
720		if err != nil {
721			return 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 err
728			}
729			defaultSlotSetBid[i] = bid
730		}
731		auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
732		donationAddress, err := c.AuctionGetDonationAddress()
733		if err != nil {
734			return err
735		}
736		auctionVariables.DonationAddress = *donationAddress
737		auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
738		if err != nil {
739			return err
740		}
741		auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
742		if err != nil {
743			return err
744		}
745		auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
746		return err
747	}); err != nil {
748		return nil, 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)"))
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)
768
769// AuctionEventsByBlock returns the events in a block that happened in the
770// Auction Smart Contract and the blockHash where the eents happened.  If there
771// are no events in that block, blockHash is nil.
772func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) {
773	var auctionEvents AuctionEvents
774	var blockHash ethCommon.Hash
775
776	query := ethereum.FilterQuery{
777		FromBlock: big.NewInt(blockNum),
778		ToBlock:   big.NewInt(blockNum),
779		Addresses: []ethCommon.Address{
780			c.address,
781		},
782		Topics: [][]ethCommon.Hash{},
783	}
784
785	logs, err := c.client.client.FilterLogs(context.TODO(), query)
786	if err != nil {
787		return nil, nil, err
788	}
789	if len(logs) > 0 {
790		blockHash = logs[0].BlockHash
791	}
792	for _, vLog := range logs {
793		if vLog.BlockHash != blockHash {
794			return nil, nil, ErrBlockHashMismatchEvent
795		}
796		switch vLog.Topics[0] {
797		case logAuctionNewBid:
798			var auxNewBid struct {
799				Slot      *big.Int
800				BidAmount *big.Int
801				Address   ethCommon.Address
802			}
803			var newBid AuctionEventNewBid
804			if err := c.contractAbi.Unpack(&auxNewBid, "NewBid", vLog.Data); err != nil {
805				return nil, nil, err
806			}
807			newBid.BidAmount = auxNewBid.BidAmount
808			newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
809			newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
810			auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
811		case logAuctionNewSlotDeadline:
812			var newSlotDeadline AuctionEventNewSlotDeadline
813			if err := c.contractAbi.Unpack(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
814				return nil, nil, err
815			}
816			auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
817		case logAuctionNewClosedAuctionSlots:
818			var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
819			if err := c.contractAbi.Unpack(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
820				return nil, nil, err
821			}
822			auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
823		case logAuctionNewOutbidding:
824			var newOutbidding AuctionEventNewOutbidding
825			if err := c.contractAbi.Unpack(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
826				return nil, nil, err
827			}
828			auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
829		case logAuctionNewDonationAddress:
830			var newDonationAddress AuctionEventNewDonationAddress
831			newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
832			auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
833		case logAuctionNewBootCoordinator:
834			var newBootCoordinator AuctionEventNewBootCoordinator
835			newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
836			auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
837		case logAuctionNewOpenAuctionSlots:
838			var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
839			if err := c.contractAbi.Unpack(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
840				return nil, nil, err
841			}
842			auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
843		case logAuctionNewAllocationRatio:
844			var newAllocationRatio AuctionEventNewAllocationRatio
845			if err := c.contractAbi.Unpack(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
846				return nil, nil, err
847			}
848			auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
849		case logAuctionSetCoordinator:
850			var setCoordinator AuctionEventSetCoordinator
851			if err := c.contractAbi.Unpack(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
852				return nil, nil, err
853			}
854			setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
855			setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
856			auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
857		case logAuctionNewForgeAllocated:
858			var newForgeAllocated AuctionEventNewForgeAllocated
859			if err := c.contractAbi.Unpack(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
860				return nil, nil, err
861			}
862			newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
863			newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
864			newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
865			auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
866		case logAuctionNewDefaultSlotSetBid:
867			var auxNewDefaultSlotSetBid struct {
868				SlotSet          *big.Int
869				NewInitialMinBid *big.Int
870			}
871			var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
872			if err := c.contractAbi.Unpack(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
873				return nil, nil, err
874			}
875			newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
876			newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
877			auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
878		case logAuctionNewForge:
879			var newForge AuctionEventNewForge
880			newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
881			newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
882			auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
883		case logAuctionHEZClaimed:
884			var HEZClaimed AuctionEventHEZClaimed
885			if err := c.contractAbi.Unpack(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
886				return nil, nil, err
887			}
888			HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
889			auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
890		}
891	}
892	return &auctionEvents, &blockHash, nil
893}