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