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.BootCoordinatorURL, err = c.auction.BootCoordinatorURL(nil)
673		if err != nil {
674			return tracerr.Wrap(err)
675		}
676		auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
677		if err != nil {
678			return tracerr.Wrap(err)
679		}
680		var defaultSlotSetBid [6]*big.Int
681		for i := uint8(0); i < 6; i++ {
682			bid, err := c.AuctionGetDefaultSlotSetBid(i)
683			if err != nil {
684				return tracerr.Wrap(err)
685			}
686			defaultSlotSetBid[i] = bid
687		}
688		auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
689		donationAddress, err := c.AuctionGetDonationAddress()
690		if err != nil {
691			return tracerr.Wrap(err)
692		}
693		auctionVariables.DonationAddress = *donationAddress
694		auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
695		if err != nil {
696			return tracerr.Wrap(err)
697		}
698		auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
699		if err != nil {
700			return tracerr.Wrap(err)
701		}
702		auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
703		return tracerr.Wrap(err)
704	}); err != nil {
705		return nil, tracerr.Wrap(err)
706	}
707	return auctionVariables, nil
708}
709
710var (
711	logAuctionNewBid                = crypto.Keccak256Hash([]byte("NewBid(uint128,uint128,address)"))
712	logAuctionNewSlotDeadline       = crypto.Keccak256Hash([]byte("NewSlotDeadline(uint8)"))
713	logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte("NewClosedAuctionSlots(uint16)"))
714	logAuctionNewOutbidding         = crypto.Keccak256Hash([]byte("NewOutbidding(uint16)"))
715	logAuctionNewDonationAddress    = crypto.Keccak256Hash([]byte("NewDonationAddress(address)"))
716	logAuctionNewBootCoordinator    = crypto.Keccak256Hash([]byte("NewBootCoordinator(address,string)"))
717	logAuctionNewOpenAuctionSlots   = crypto.Keccak256Hash([]byte("NewOpenAuctionSlots(uint16)"))
718	logAuctionNewAllocationRatio    = crypto.Keccak256Hash([]byte("NewAllocationRatio(uint16[3])"))
719	logAuctionSetCoordinator        = crypto.Keccak256Hash([]byte("SetCoordinator(address,address,string)"))
720	logAuctionNewForgeAllocated     = crypto.Keccak256Hash([]byte("NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
721	logAuctionNewDefaultSlotSetBid  = crypto.Keccak256Hash([]byte("NewDefaultSlotSetBid(uint128,uint128)"))
722	logAuctionNewForge              = crypto.Keccak256Hash([]byte("NewForge(address,uint128)"))
723	logAuctionHEZClaimed            = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)"))
724)
725
726// AuctionEventsByBlock returns the events in a block that happened in the
727// Auction Smart Contract and the blockHash where the eents happened.  If there
728// are no events in that block, blockHash is nil.
729func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) {
730	var auctionEvents AuctionEvents
731	var blockHash *ethCommon.Hash
732
733	query := ethereum.FilterQuery{
734		FromBlock: big.NewInt(blockNum),
735		ToBlock:   big.NewInt(blockNum),
736		Addresses: []ethCommon.Address{
737			c.address,
738		},
739		Topics: [][]ethCommon.Hash{},
740	}
741
742	logs, err := c.client.client.FilterLogs(context.TODO(), query)
743	if err != nil {
744		return nil, nil, tracerr.Wrap(err)
745	}
746	if len(logs) > 0 {
747		blockHash = &logs[0].BlockHash
748	}
749	for _, vLog := range logs {
750		if vLog.BlockHash != *blockHash {
751			log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
752			return nil, nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
753		}
754		switch vLog.Topics[0] {
755		case logAuctionNewBid:
756			var auxNewBid struct {
757				Slot      *big.Int
758				BidAmount *big.Int
759				Address   ethCommon.Address
760			}
761			var newBid AuctionEventNewBid
762			if err := c.contractAbi.Unpack(&auxNewBid, "NewBid", vLog.Data); err != nil {
763				return nil, nil, tracerr.Wrap(err)
764			}
765			newBid.BidAmount = auxNewBid.BidAmount
766			newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
767			newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
768			auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
769		case logAuctionNewSlotDeadline:
770			var newSlotDeadline AuctionEventNewSlotDeadline
771			if err := c.contractAbi.Unpack(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
772				return nil, nil, tracerr.Wrap(err)
773			}
774			auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
775		case logAuctionNewClosedAuctionSlots:
776			var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
777			if err := c.contractAbi.Unpack(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
778				return nil, nil, tracerr.Wrap(err)
779			}
780			auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
781		case logAuctionNewOutbidding:
782			var newOutbidding AuctionEventNewOutbidding
783			if err := c.contractAbi.Unpack(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
784				return nil, nil, tracerr.Wrap(err)
785			}
786			auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
787		case logAuctionNewDonationAddress:
788			var newDonationAddress AuctionEventNewDonationAddress
789			newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
790			auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
791		case logAuctionNewBootCoordinator:
792			var newBootCoordinator AuctionEventNewBootCoordinator
793			if err := c.contractAbi.Unpack(&newBootCoordinator, "NewBootCoordinator", vLog.Data); err != nil {
794				return nil, nil, tracerr.Wrap(err)
795			}
796			newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
797			auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
798		case logAuctionNewOpenAuctionSlots:
799			var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
800			if err := c.contractAbi.Unpack(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
801				return nil, nil, tracerr.Wrap(err)
802			}
803			auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
804		case logAuctionNewAllocationRatio:
805			var newAllocationRatio AuctionEventNewAllocationRatio
806			if err := c.contractAbi.Unpack(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
807				return nil, nil, tracerr.Wrap(err)
808			}
809			auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
810		case logAuctionSetCoordinator:
811			var setCoordinator AuctionEventSetCoordinator
812			if err := c.contractAbi.Unpack(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
813				return nil, nil, tracerr.Wrap(err)
814			}
815			setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
816			setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
817			auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
818		case logAuctionNewForgeAllocated:
819			var newForgeAllocated AuctionEventNewForgeAllocated
820			if err := c.contractAbi.Unpack(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
821				return nil, nil, tracerr.Wrap(err)
822			}
823			newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
824			newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
825			newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
826			auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
827		case logAuctionNewDefaultSlotSetBid:
828			var auxNewDefaultSlotSetBid struct {
829				SlotSet          *big.Int
830				NewInitialMinBid *big.Int
831			}
832			var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
833			if err := c.contractAbi.Unpack(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
834				return nil, nil, tracerr.Wrap(err)
835			}
836			newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
837			newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
838			auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
839		case logAuctionNewForge:
840			var newForge AuctionEventNewForge
841			newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
842			newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
843			auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
844		case logAuctionHEZClaimed:
845			var HEZClaimed AuctionEventHEZClaimed
846			if err := c.contractAbi.Unpack(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
847				return nil, nil, tracerr.Wrap(err)
848			}
849			HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
850			auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
851		}
852	}
853	return &auctionEvents, blockHash, nil
854}