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