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