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