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