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