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