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