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