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