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