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