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