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