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