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