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