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