arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/eth/auction.go
eth/auction.goRaw
   1package eth
   2
   3import (
   4	"context"
   5	"encoding/binary"
   6	"fmt"
   7	"math/big"
   8	"strings"
   9
  10	"github.com/ethereum/go-ethereum"
  11	"github.com/ethereum/go-ethereum/accounts/abi"
  12	"github.com/ethereum/go-ethereum/accounts/abi/bind"
  13	ethCommon "github.com/ethereum/go-ethereum/common"
  14	"github.com/ethereum/go-ethereum/core/types"
  15	"github.com/ethereum/go-ethereum/crypto"
  16	"github.com/ethereum/go-ethereum/ethclient"
  17	HermezAuctionProtocol "github.com/hermeznetwork/hermez-node/eth/contracts/auction"
  18	ERC777 "github.com/hermeznetwork/hermez-node/eth/contracts/erc777"
  19	"golang.org/x/crypto/sha3"
  20)
  21
  22// AuctionConstants are the constants of the Rollup Smart Contract
  23type AuctionConstants struct {
  24	// Blocks per slot
  25	BlocksPerSlot uint8
  26	// Minimum bid when no one has bid yet
  27	InitialMinimalBidding *big.Int
  28	// First block where the first slot begins
  29	GenesisBlockNum int64
  30	// ERC777 token with which the bids will be made
  31	TokenHEZ ethCommon.Address
  32	// HermezRollup smartcontract address
  33	HermezRollup ethCommon.Address
  34	// Hermez Governanze Token smartcontract address who controls some parameters and collects HEZ fee
  35	// Only for test
  36	GovernanceAddress ethCommon.Address
  37}
  38
  39// SlotState is the state of a slot
  40type SlotState struct {
  41	Bidder       ethCommon.Address
  42	Fulfilled    bool
  43	BidAmount    *big.Int
  44	ClosedMinBid *big.Int
  45}
  46
  47// NewSlotState returns an empty SlotState
  48func NewSlotState() *SlotState {
  49	return &SlotState{
  50		Bidder:       ethCommon.Address{},
  51		Fulfilled:    false,
  52		BidAmount:    big.NewInt(0),
  53		ClosedMinBid: big.NewInt(0),
  54	}
  55}
  56
  57// Coordinator is the details of the Coordinator identified by the forger address
  58type Coordinator struct {
  59	Forger ethCommon.Address
  60	URL    string
  61}
  62
  63// AuctionVariables are the variables of the Auction Smart Contract
  64type AuctionVariables struct {
  65	// Boot Coordinator Address
  66	DonationAddress ethCommon.Address
  67	// Boot Coordinator Address
  68	BootCoordinator ethCommon.Address
  69	// The minimum bid value in a series of 6 slots
  70	DefaultSlotSetBid [6]*big.Int
  71	// Distance (#slots) to the closest slot to which you can bid ( 2 Slots = 2 * 40 Blocks = 20 min )
  72	ClosedAuctionSlots uint16
  73	// Distance (#slots) to the farthest slot to which you can bid (30 days = 4320 slots )
  74	OpenAuctionSlots uint16
  75	// How the HEZ tokens deposited by the slot winner are distributed (Burn: 40% - Donation: 40% - HGT: 20%)
  76	AllocationRatio [3]uint16
  77	// Minimum outbid (percentage) over the previous one to consider it valid
  78	Outbidding uint16
  79	// Number of blocks at the end of a slot in which any coordinator can forge if the winner has not forged one before
  80	SlotDeadline uint8
  81}
  82
  83// AuctionState represents the state of the Rollup in the Smart Contract
  84type AuctionState struct {
  85	// Mapping to control slot state
  86	Slots map[int64]*SlotState
  87	// Mapping to control balances pending to claim
  88	PendingBalances map[ethCommon.Address]*big.Int
  89	// Mapping to register all the coordinators. The address used for the mapping is the forger address
  90	Coordinators map[ethCommon.Address]*Coordinator
  91}
  92
  93// AuctionEventNewBid is an event of the Auction Smart Contract
  94type AuctionEventNewBid struct {
  95	Slot      int64
  96	BidAmount *big.Int
  97	Bidder    ethCommon.Address
  98}
  99
 100// AuctionEventNewSlotDeadline is an event of the Auction Smart Contract
 101type AuctionEventNewSlotDeadline struct {
 102	NewSlotDeadline uint8
 103}
 104
 105// AuctionEventNewClosedAuctionSlots is an event of the Auction Smart Contract
 106type AuctionEventNewClosedAuctionSlots struct {
 107	NewClosedAuctionSlots uint16
 108}
 109
 110// AuctionEventNewOutbidding is an event of the Auction Smart Contract
 111type AuctionEventNewOutbidding struct {
 112	NewOutbidding uint16
 113}
 114
 115// AuctionEventNewDonationAddress is an event of the Auction Smart Contract
 116type AuctionEventNewDonationAddress struct {
 117	NewDonationAddress ethCommon.Address
 118}
 119
 120// AuctionEventNewBootCoordinator is an event of the Auction Smart Contract
 121type AuctionEventNewBootCoordinator struct {
 122	NewBootCoordinator ethCommon.Address
 123}
 124
 125// AuctionEventNewOpenAuctionSlots is an event of the Auction Smart Contract
 126type AuctionEventNewOpenAuctionSlots struct {
 127	NewOpenAuctionSlots uint16
 128}
 129
 130// AuctionEventNewAllocationRatio is an event of the Auction Smart Contract
 131type AuctionEventNewAllocationRatio struct {
 132	NewAllocationRatio [3]uint16
 133}
 134
 135// AuctionEventSetCoordinator is an event of the Auction Smart Contract
 136type AuctionEventSetCoordinator struct {
 137	BidderAddress  ethCommon.Address
 138	ForgerAddress  ethCommon.Address
 139	CoordinatorURL string
 140}
 141
 142// AuctionEventNewForgeAllocated is an event of the Auction Smart Contract
 143type AuctionEventNewForgeAllocated struct {
 144	Bidder           ethCommon.Address
 145	Forger           ethCommon.Address
 146	SlotToForge      int64
 147	BurnAmount       *big.Int
 148	DonationAmount   *big.Int
 149	GovernanceAmount *big.Int
 150}
 151
 152// AuctionEventNewDefaultSlotSetBid is an event of the Auction Smart Contract
 153type AuctionEventNewDefaultSlotSetBid struct {
 154	SlotSet          int64
 155	NewInitialMinBid *big.Int
 156}
 157
 158// AuctionEventNewForge is an event of the Auction Smart Contract
 159type AuctionEventNewForge struct {
 160	Forger      ethCommon.Address
 161	SlotToForge int64
 162}
 163
 164// AuctionEventHEZClaimed is an event of the Auction Smart Contract
 165type AuctionEventHEZClaimed struct {
 166	Owner  ethCommon.Address
 167	Amount *big.Int
 168}
 169
 170// AuctionEvents is the list of events in a block of the Auction Smart Contract
 171type AuctionEvents struct { //nolint:structcheck
 172	NewBid                []AuctionEventNewBid
 173	NewSlotDeadline       []AuctionEventNewSlotDeadline
 174	NewClosedAuctionSlots []AuctionEventNewClosedAuctionSlots
 175	NewOutbidding         []AuctionEventNewOutbidding
 176	NewDonationAddress    []AuctionEventNewDonationAddress
 177	NewBootCoordinator    []AuctionEventNewBootCoordinator
 178	NewOpenAuctionSlots   []AuctionEventNewOpenAuctionSlots
 179	NewAllocationRatio    []AuctionEventNewAllocationRatio
 180	SetCoordinator        []AuctionEventSetCoordinator
 181	NewForgeAllocated     []AuctionEventNewForgeAllocated
 182	NewDefaultSlotSetBid  []AuctionEventNewDefaultSlotSetBid
 183	NewForge              []AuctionEventNewForge
 184	HEZClaimed            []AuctionEventHEZClaimed
 185}
 186
 187// NewAuctionEvents creates an empty AuctionEvents with the slices initialized.
 188func NewAuctionEvents() AuctionEvents {
 189	return AuctionEvents{
 190		NewBid:                make([]AuctionEventNewBid, 0),
 191		NewSlotDeadline:       make([]AuctionEventNewSlotDeadline, 0),
 192		NewClosedAuctionSlots: make([]AuctionEventNewClosedAuctionSlots, 0),
 193		NewOutbidding:         make([]AuctionEventNewOutbidding, 0),
 194		NewDonationAddress:    make([]AuctionEventNewDonationAddress, 0),
 195		NewBootCoordinator:    make([]AuctionEventNewBootCoordinator, 0),
 196		NewOpenAuctionSlots:   make([]AuctionEventNewOpenAuctionSlots, 0),
 197		NewAllocationRatio:    make([]AuctionEventNewAllocationRatio, 0),
 198		SetCoordinator:        make([]AuctionEventSetCoordinator, 0),
 199		NewForgeAllocated:     make([]AuctionEventNewForgeAllocated, 0),
 200		NewDefaultSlotSetBid:  make([]AuctionEventNewDefaultSlotSetBid, 0),
 201		NewForge:              make([]AuctionEventNewForge, 0),
 202		HEZClaimed:            make([]AuctionEventHEZClaimed, 0),
 203	}
 204}
 205
 206// AuctionInterface is the inteface to to Auction Smart Contract
 207type AuctionInterface interface {
 208	//
 209	// Smart Contract Methods
 210	//
 211
 212	// Getter/Setter, where Setter is onlyOwner
 213	AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error)
 214	AuctionGetSlotDeadline() (uint8, error)
 215	AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error)
 216	AuctionGetOpenAuctionSlots() (uint16, error)
 217	AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error)
 218	AuctionGetClosedAuctionSlots() (uint16, error)
 219	AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error)
 220	AuctionGetOutbidding() (uint16, error)
 221	AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error)
 222	AuctionGetAllocationRatio() ([3]uint16, error)
 223	AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error)
 224	AuctionGetDonationAddress() (*ethCommon.Address, error)
 225	AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (*types.Transaction, error)
 226	AuctionGetBootCoordinator() (*ethCommon.Address, error)
 227	AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (*types.Transaction, error)
 228
 229	// Coordinator Management
 230	AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (*types.Transaction, error)
 231
 232	// Slot Info
 233	AuctionGetSlotNumber(blockNum int64) (int64, error)
 234	AuctionGetCurrentSlotNumber() (int64, error)
 235	AuctionGetMinBidBySlot(slot int64) (*big.Int, error)
 236	AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error)
 237	AuctionGetSlotSet(slot int64) (*big.Int, error)
 238
 239	// Bidding
 240	AuctionBid(slot int64, bidAmount *big.Int) (*types.Transaction, error)
 241	AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int) (*types.Transaction, error)
 242
 243	// Forge
 244	AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error)
 245	AuctionForge(forger ethCommon.Address) (*types.Transaction, error)
 246
 247	// Fees
 248	AuctionClaimHEZ() (*types.Transaction, error)
 249	AuctionGetClaimableHEZ(bidder ethCommon.Address) (*big.Int, error)
 250
 251	//
 252	// Smart Contract Status
 253	//
 254
 255	AuctionConstants() (*AuctionConstants, error)
 256	AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error)
 257}
 258
 259//
 260// Implementation
 261//
 262
 263// AuctionClient is the implementation of the interface to the Auction Smart Contract in ethereum.
 264type AuctionClient struct {
 265	client       *EthereumClient
 266	address      ethCommon.Address
 267	tokenAddress ethCommon.Address
 268	gasLimit     uint64
 269	contractAbi  abi.ABI
 270}
 271
 272// NewAuctionClient creates a new AuctionClient.  `tokenAddress` is the address of the HEZ tokens.
 273func NewAuctionClient(client *EthereumClient, address, tokenAddress ethCommon.Address) (*AuctionClient, error) {
 274	contractAbi, err := abi.JSON(strings.NewReader(string(HermezAuctionProtocol.HermezAuctionProtocolABI)))
 275	if err != nil {
 276		return nil, err
 277	}
 278	return &AuctionClient{
 279		client:       client,
 280		address:      address,
 281		tokenAddress: tokenAddress,
 282		gasLimit:     1000000, //nolint:gomnd
 283		contractAbi:  contractAbi,
 284	}, nil
 285}
 286
 287// AuctionSetSlotDeadline is the interface to call the smart contract function
 288func (c *AuctionClient) AuctionSetSlotDeadline(newDeadline uint8) (*types.Transaction, error) {
 289	var tx *types.Transaction
 290	var err error
 291	if tx, err = c.client.CallAuth(
 292		c.gasLimit,
 293		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 294			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 295			if err != nil {
 296				return nil, err
 297			}
 298			return auction.SetSlotDeadline(auth, newDeadline)
 299		},
 300	); err != nil {
 301		return nil, fmt.Errorf("Failed setting slotDeadline: %w", err)
 302	}
 303	return tx, nil
 304}
 305
 306// AuctionGetSlotDeadline is the interface to call the smart contract function
 307func (c *AuctionClient) AuctionGetSlotDeadline() (uint8, error) {
 308	var slotDeadline uint8
 309	if err := c.client.Call(func(ec *ethclient.Client) error {
 310		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 311		if err != nil {
 312			return err
 313		}
 314		slotDeadline, err = auction.GetSlotDeadline(nil)
 315		return err
 316	}); err != nil {
 317		return 0, err
 318	}
 319	return slotDeadline, nil
 320}
 321
 322// AuctionSetOpenAuctionSlots is the interface to call the smart contract function
 323func (c *AuctionClient) AuctionSetOpenAuctionSlots(newOpenAuctionSlots uint16) (*types.Transaction, error) {
 324	var tx *types.Transaction
 325	var err error
 326	if tx, err = c.client.CallAuth(
 327		c.gasLimit,
 328		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 329			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 330			if err != nil {
 331				return nil, err
 332			}
 333			return auction.SetOpenAuctionSlots(auth, newOpenAuctionSlots)
 334		},
 335	); err != nil {
 336		return nil, fmt.Errorf("Failed setting openAuctionSlots: %w", err)
 337	}
 338	return tx, nil
 339}
 340
 341// AuctionGetOpenAuctionSlots is the interface to call the smart contract function
 342func (c *AuctionClient) AuctionGetOpenAuctionSlots() (uint16, error) {
 343	var openAuctionSlots uint16
 344	if err := c.client.Call(func(ec *ethclient.Client) error {
 345		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 346		if err != nil {
 347			return err
 348		}
 349		openAuctionSlots, err = auction.GetOpenAuctionSlots(nil)
 350		return err
 351	}); err != nil {
 352		return 0, err
 353	}
 354	return openAuctionSlots, nil
 355}
 356
 357// AuctionSetClosedAuctionSlots is the interface to call the smart contract function
 358func (c *AuctionClient) AuctionSetClosedAuctionSlots(newClosedAuctionSlots uint16) (*types.Transaction, error) {
 359	var tx *types.Transaction
 360	var err error
 361	if tx, err = c.client.CallAuth(
 362		c.gasLimit,
 363		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 364			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 365			if err != nil {
 366				return nil, err
 367			}
 368			return auction.SetClosedAuctionSlots(auth, newClosedAuctionSlots)
 369		},
 370	); err != nil {
 371		return nil, fmt.Errorf("Failed setting closedAuctionSlots: %w", err)
 372	}
 373	return tx, nil
 374}
 375
 376// AuctionGetClosedAuctionSlots is the interface to call the smart contract function
 377func (c *AuctionClient) AuctionGetClosedAuctionSlots() (uint16, error) {
 378	var closedAuctionSlots uint16
 379	if err := c.client.Call(func(ec *ethclient.Client) error {
 380		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 381		if err != nil {
 382			return err
 383		}
 384		closedAuctionSlots, err = auction.GetClosedAuctionSlots(nil)
 385		return err
 386	}); err != nil {
 387		return 0, err
 388	}
 389	return closedAuctionSlots, nil
 390}
 391
 392// AuctionSetOutbidding is the interface to call the smart contract function
 393func (c *AuctionClient) AuctionSetOutbidding(newOutbidding uint16) (*types.Transaction, error) {
 394	var tx *types.Transaction
 395	var err error
 396	if tx, err = c.client.CallAuth(
 397		12500000, //nolint:gomnd
 398		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 399			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 400			if err != nil {
 401				return nil, err
 402			}
 403			return auction.SetOutbidding(auth, newOutbidding)
 404		},
 405	); err != nil {
 406		return nil, fmt.Errorf("Failed setting setOutbidding: %w", err)
 407	}
 408	return tx, nil
 409}
 410
 411// AuctionGetOutbidding is the interface to call the smart contract function
 412func (c *AuctionClient) AuctionGetOutbidding() (uint16, error) {
 413	var outbidding uint16
 414	if err := c.client.Call(func(ec *ethclient.Client) error {
 415		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 416		if err != nil {
 417			return err
 418		}
 419		outbidding, err = auction.GetOutbidding(nil)
 420		return err
 421	}); err != nil {
 422		return 0, err
 423	}
 424	return outbidding, nil
 425}
 426
 427// AuctionSetAllocationRatio is the interface to call the smart contract function
 428func (c *AuctionClient) AuctionSetAllocationRatio(newAllocationRatio [3]uint16) (*types.Transaction, error) {
 429	var tx *types.Transaction
 430	var err error
 431	if tx, err = c.client.CallAuth(
 432		c.gasLimit,
 433		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 434			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 435			if err != nil {
 436				return nil, err
 437			}
 438			return auction.SetAllocationRatio(auth, newAllocationRatio)
 439		},
 440	); err != nil {
 441		return nil, fmt.Errorf("Failed setting allocationRatio: %w", err)
 442	}
 443	return tx, nil
 444}
 445
 446// AuctionGetAllocationRatio is the interface to call the smart contract function
 447func (c *AuctionClient) AuctionGetAllocationRatio() ([3]uint16, error) {
 448	var allocationRation [3]uint16
 449	if err := c.client.Call(func(ec *ethclient.Client) error {
 450		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 451		if err != nil {
 452			return err
 453		}
 454		allocationRation, err = auction.GetAllocationRatio(nil)
 455		return err
 456	}); err != nil {
 457		return [3]uint16{}, err
 458	}
 459	return allocationRation, nil
 460}
 461
 462// AuctionSetDonationAddress is the interface to call the smart contract function
 463func (c *AuctionClient) AuctionSetDonationAddress(newDonationAddress ethCommon.Address) (*types.Transaction, error) {
 464	var tx *types.Transaction
 465	var err error
 466	if tx, err = c.client.CallAuth(
 467		c.gasLimit,
 468		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 469			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 470			if err != nil {
 471				return nil, err
 472			}
 473			return auction.SetDonationAddress(auth, newDonationAddress)
 474		},
 475	); err != nil {
 476		return nil, fmt.Errorf("Failed setting donationAddress: %w", err)
 477	}
 478	return tx, nil
 479}
 480
 481// AuctionGetDonationAddress is the interface to call the smart contract function
 482func (c *AuctionClient) AuctionGetDonationAddress() (*ethCommon.Address, error) {
 483	var donationAddress ethCommon.Address
 484	if err := c.client.Call(func(ec *ethclient.Client) error {
 485		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 486		if err != nil {
 487			return err
 488		}
 489		donationAddress, err = auction.GetDonationAddress(nil)
 490		return err
 491	}); err != nil {
 492		return nil, err
 493	}
 494	return &donationAddress, nil
 495}
 496
 497// AuctionSetBootCoordinator is the interface to call the smart contract function
 498func (c *AuctionClient) AuctionSetBootCoordinator(newBootCoordinator ethCommon.Address) (*types.Transaction, error) {
 499	var tx *types.Transaction
 500	var err error
 501	if tx, err = c.client.CallAuth(
 502		c.gasLimit,
 503		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 504			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 505			if err != nil {
 506				return nil, err
 507			}
 508			return auction.SetBootCoordinator(auth, newBootCoordinator)
 509		},
 510	); err != nil {
 511		return nil, fmt.Errorf("Failed setting bootCoordinator: %w", err)
 512	}
 513	return tx, nil
 514}
 515
 516// AuctionGetBootCoordinator is the interface to call the smart contract function
 517func (c *AuctionClient) AuctionGetBootCoordinator() (*ethCommon.Address, error) {
 518	var bootCoordinator ethCommon.Address
 519	if err := c.client.Call(func(ec *ethclient.Client) error {
 520		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 521		if err != nil {
 522			return err
 523		}
 524		bootCoordinator, err = auction.GetBootCoordinator(nil)
 525		return err
 526	}); err != nil {
 527		return nil, err
 528	}
 529	return &bootCoordinator, nil
 530}
 531
 532// AuctionChangeDefaultSlotSetBid is the interface to call the smart contract function
 533func (c *AuctionClient) AuctionChangeDefaultSlotSetBid(slotSet int64, newInitialMinBid *big.Int) (*types.Transaction, error) {
 534	var tx *types.Transaction
 535	var err error
 536	if tx, err = c.client.CallAuth(
 537		c.gasLimit,
 538		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 539			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 540			if err != nil {
 541				return nil, err
 542			}
 543			slotSetToSend := big.NewInt(slotSet)
 544			return auction.ChangeDefaultSlotSetBid(auth, slotSetToSend, newInitialMinBid)
 545		},
 546	); err != nil {
 547		return nil, fmt.Errorf("Failed changing slotSet Bid: %w", err)
 548	}
 549	return tx, nil
 550}
 551
 552// AuctionGetClaimableHEZ is the interface to call the smart contract function
 553func (c *AuctionClient) AuctionGetClaimableHEZ(claimAddress ethCommon.Address) (*big.Int, error) {
 554	var claimableHEZ *big.Int
 555	if err := c.client.Call(func(ec *ethclient.Client) error {
 556		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 557		if err != nil {
 558			return err
 559		}
 560		claimableHEZ, err = auction.GetClaimableHEZ(nil, claimAddress)
 561		return err
 562	}); err != nil {
 563		return nil, err
 564	}
 565	return claimableHEZ, nil
 566}
 567
 568// AuctionSetCoordinator is the interface to call the smart contract function
 569func (c *AuctionClient) AuctionSetCoordinator(forger ethCommon.Address, coordinatorURL string) (*types.Transaction, error) {
 570	var tx *types.Transaction
 571	var err error
 572	if tx, err = c.client.CallAuth(
 573		c.gasLimit,
 574		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 575			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 576			if err != nil {
 577				return nil, err
 578			}
 579			return auction.SetCoordinator(auth, forger, coordinatorURL)
 580		},
 581	); err != nil {
 582		return nil, fmt.Errorf("Failed set coordinator: %w", err)
 583	}
 584	return tx, nil
 585}
 586
 587// AuctionGetCurrentSlotNumber is the interface to call the smart contract function
 588func (c *AuctionClient) AuctionGetCurrentSlotNumber() (int64, error) {
 589	var _currentSlotNumber *big.Int
 590	if err := c.client.Call(func(ec *ethclient.Client) error {
 591		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 592		if err != nil {
 593			return err
 594		}
 595		_currentSlotNumber, err = auction.GetCurrentSlotNumber(nil)
 596		return err
 597	}); err != nil {
 598		return 0, err
 599	}
 600	currentSlotNumber := _currentSlotNumber.Int64()
 601	return currentSlotNumber, nil
 602}
 603
 604// AuctionGetMinBidBySlot is the interface to call the smart contract function
 605func (c *AuctionClient) AuctionGetMinBidBySlot(slot int64) (*big.Int, error) {
 606	var minBid *big.Int
 607	if err := c.client.Call(func(ec *ethclient.Client) error {
 608		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 609		if err != nil {
 610			return err
 611		}
 612		slotToSend := big.NewInt(slot)
 613		minBid, err = auction.GetMinBidBySlot(nil, slotToSend)
 614		return err
 615	}); err != nil {
 616		return big.NewInt(0), err
 617	}
 618	return minBid, nil
 619}
 620
 621// AuctionGetSlotSet is the interface to call the smart contract function
 622func (c *AuctionClient) AuctionGetSlotSet(slot int64) (*big.Int, error) {
 623	var slotSet *big.Int
 624	if err := c.client.Call(func(ec *ethclient.Client) error {
 625		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 626		if err != nil {
 627			return err
 628		}
 629		slotToSend := big.NewInt(slot)
 630		slotSet, err = auction.GetSlotSet(nil, slotToSend)
 631		return err
 632	}); err != nil {
 633		return big.NewInt(0), err
 634	}
 635	return slotSet, nil
 636}
 637
 638// AuctionGetDefaultSlotSetBid is the interface to call the smart contract function
 639func (c *AuctionClient) AuctionGetDefaultSlotSetBid(slotSet uint8) (*big.Int, error) {
 640	var minBidSlotSet *big.Int
 641	if err := c.client.Call(func(ec *ethclient.Client) error {
 642		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 643		if err != nil {
 644			return err
 645		}
 646		minBidSlotSet, err = auction.GetDefaultSlotSetBid(nil, slotSet)
 647		return err
 648	}); err != nil {
 649		return big.NewInt(0), err
 650	}
 651	return minBidSlotSet, nil
 652}
 653
 654// AuctionGetSlotNumber is the interface to call the smart contract function
 655func (c *AuctionClient) AuctionGetSlotNumber(blockNum int64) (int64, error) {
 656	var slot *big.Int
 657	if err := c.client.Call(func(ec *ethclient.Client) error {
 658		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 659		if err != nil {
 660			return err
 661		}
 662		blockNumBig := big.NewInt(blockNum)
 663		slot, err = auction.GetSlotNumber(nil, blockNumBig)
 664		return err
 665	}); err != nil {
 666		return 0, err
 667	}
 668	return slot.Int64(), nil
 669}
 670
 671// AuctionBid is the interface to call the smart contract function
 672func (c *AuctionClient) AuctionBid(slot int64, bidAmount *big.Int) (*types.Transaction, error) {
 673	var tx *types.Transaction
 674	var err error
 675	if tx, err = c.client.CallAuth(
 676		c.gasLimit,
 677		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 678			tokens, err := ERC777.NewERC777(c.tokenAddress, ec)
 679			if err != nil {
 680				return nil, err
 681			}
 682			bidFnSignature := []byte("bid(uint128,uint128)")
 683			hash := sha3.NewLegacyKeccak256()
 684			_, err = hash.Write(bidFnSignature)
 685			if err != nil {
 686				return nil, err
 687			}
 688			methodID := hash.Sum(nil)[:4]
 689			slotBytes := make([]byte, 8)
 690			binary.BigEndian.PutUint64(slotBytes, uint64(slot))
 691			paddedSlot := ethCommon.LeftPadBytes(slotBytes, 32)
 692			paddedAmount := ethCommon.LeftPadBytes(bidAmount.Bytes(), 32)
 693			var userData []byte
 694			userData = append(userData, methodID...)
 695			userData = append(userData, paddedSlot...)
 696			userData = append(userData, paddedAmount...)
 697			return tokens.Send(auth, c.address, bidAmount, userData)
 698		},
 699	); err != nil {
 700		return nil, fmt.Errorf("Failed bid: %w", err)
 701	}
 702	return tx, nil
 703}
 704
 705// AuctionMultiBid is the interface to call the smart contract function
 706func (c *AuctionClient) AuctionMultiBid(startingSlot int64, endingSlot int64, slotSet [6]bool, maxBid, closedMinBid, budget *big.Int) (*types.Transaction, error) {
 707	var tx *types.Transaction
 708	var err error
 709	if tx, err = c.client.CallAuth(
 710		c.gasLimit,
 711		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 712			tokens, err := ERC777.NewERC777(c.tokenAddress, ec)
 713			if err != nil {
 714				return nil, err
 715			}
 716			multiBidFnSignature := []byte("multiBid(uint128,uint128,bool[6],uint128,uint128)")
 717			hash := sha3.NewLegacyKeccak256()
 718			_, err = hash.Write(multiBidFnSignature)
 719			if err != nil {
 720				return nil, err
 721			}
 722			methodID := hash.Sum(nil)[:4]
 723			startingSlotBytes := make([]byte, 8)
 724			binary.BigEndian.PutUint64(startingSlotBytes, uint64(startingSlot))
 725			paddedStartingSlot := ethCommon.LeftPadBytes(startingSlotBytes, 32)
 726			endingSlotBytes := make([]byte, 8)
 727			binary.BigEndian.PutUint64(endingSlotBytes, uint64(endingSlot))
 728			paddedEndingSlot := ethCommon.LeftPadBytes(endingSlotBytes, 32)
 729			paddedMinBid := ethCommon.LeftPadBytes(closedMinBid.Bytes(), 32)
 730			paddedMaxBid := ethCommon.LeftPadBytes(maxBid.Bytes(), 32)
 731			var userData []byte
 732			userData = append(userData, methodID...)
 733			userData = append(userData, paddedStartingSlot...)
 734			userData = append(userData, paddedEndingSlot...)
 735			for i := 0; i < len(slotSet); i++ {
 736				if slotSet[i] {
 737					paddedSlotSet := ethCommon.LeftPadBytes([]byte{1}, 32)
 738					userData = append(userData, paddedSlotSet...)
 739				} else {
 740					paddedSlotSet := ethCommon.LeftPadBytes([]byte{0}, 32)
 741					userData = append(userData, paddedSlotSet...)
 742				}
 743			}
 744			userData = append(userData, paddedMaxBid...)
 745			userData = append(userData, paddedMinBid...)
 746			return tokens.Send(auth, c.address, budget, userData)
 747		},
 748	); err != nil {
 749		return nil, fmt.Errorf("Failed multibid: %w", err)
 750	}
 751	return tx, nil
 752}
 753
 754// AuctionCanForge is the interface to call the smart contract function
 755func (c *AuctionClient) AuctionCanForge(forger ethCommon.Address, blockNum int64) (bool, error) {
 756	var canForge bool
 757	if err := c.client.Call(func(ec *ethclient.Client) error {
 758		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 759		if err != nil {
 760			return err
 761		}
 762		canForge, err = auction.CanForge(nil, forger, big.NewInt(blockNum))
 763		return err
 764	}); err != nil {
 765		return false, err
 766	}
 767	return canForge, nil
 768}
 769
 770// AuctionClaimHEZ is the interface to call the smart contract function
 771func (c *AuctionClient) AuctionClaimHEZ() (*types.Transaction, error) {
 772	var tx *types.Transaction
 773	var err error
 774	if tx, err = c.client.CallAuth(
 775		c.gasLimit,
 776		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 777			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 778			if err != nil {
 779				return nil, err
 780			}
 781			return auction.ClaimHEZ(auth)
 782		},
 783	); err != nil {
 784		return nil, fmt.Errorf("Failed claim HEZ: %w", err)
 785	}
 786	return tx, nil
 787}
 788
 789// AuctionForge is the interface to call the smart contract function
 790func (c *AuctionClient) AuctionForge(forger ethCommon.Address) (*types.Transaction, error) {
 791	var tx *types.Transaction
 792	var err error
 793	if tx, err = c.client.CallAuth(
 794		c.gasLimit,
 795		func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
 796			auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 797			if err != nil {
 798				return nil, err
 799			}
 800			return auction.Forge(auth, forger)
 801		},
 802	); err != nil {
 803		return nil, fmt.Errorf("Failed forge: %w", err)
 804	}
 805	return tx, nil
 806}
 807
 808// AuctionConstants returns the Constants of the Auction Smart Contract
 809func (c *AuctionClient) AuctionConstants() (*AuctionConstants, error) {
 810	auctionConstants := new(AuctionConstants)
 811	if err := c.client.Call(func(ec *ethclient.Client) error {
 812		auction, err := HermezAuctionProtocol.NewHermezAuctionProtocol(c.address, ec)
 813		if err != nil {
 814			return err
 815		}
 816		auctionConstants.BlocksPerSlot, err = auction.BLOCKSPERSLOT(nil)
 817		if err != nil {
 818			return err
 819		}
 820		genesisBlock, err := auction.GenesisBlock(nil)
 821		if err != nil {
 822			return err
 823		}
 824		auctionConstants.GenesisBlockNum = genesisBlock.Int64()
 825		auctionConstants.HermezRollup, err = auction.HermezRollup(nil)
 826		if err != nil {
 827			return err
 828		}
 829		auctionConstants.InitialMinimalBidding, err = auction.INITIALMINIMALBIDDING(nil)
 830		if err != nil {
 831			return err
 832		}
 833		auctionConstants.TokenHEZ, err = auction.TokenHEZ(nil)
 834		return err
 835	}); err != nil {
 836		return nil, err
 837	}
 838	return auctionConstants, nil
 839}
 840
 841// AuctionVariables returns the variables of the Auction Smart Contract
 842func (c *AuctionClient) AuctionVariables() (*AuctionVariables, error) {
 843	auctionVariables := new(AuctionVariables)
 844	if err := c.client.Call(func(ec *ethclient.Client) error {
 845		var err error
 846		auctionVariables.AllocationRatio, err = c.AuctionGetAllocationRatio()
 847		if err != nil {
 848			return err
 849		}
 850		bootCoordinator, err := c.AuctionGetBootCoordinator()
 851		if err != nil {
 852			return err
 853		}
 854		auctionVariables.BootCoordinator = *bootCoordinator
 855		auctionVariables.ClosedAuctionSlots, err = c.AuctionGetClosedAuctionSlots()
 856		if err != nil {
 857			return err
 858		}
 859		var defaultSlotSetBid [6]*big.Int
 860		for i := uint8(0); i < 6; i++ {
 861			bid, err := c.AuctionGetDefaultSlotSetBid(i)
 862			if err != nil {
 863				return err
 864			}
 865			defaultSlotSetBid[i] = bid
 866		}
 867		auctionVariables.DefaultSlotSetBid = defaultSlotSetBid
 868		donationAddress, err := c.AuctionGetDonationAddress()
 869		if err != nil {
 870			return err
 871		}
 872		auctionVariables.DonationAddress = *donationAddress
 873		auctionVariables.OpenAuctionSlots, err = c.AuctionGetOpenAuctionSlots()
 874		if err != nil {
 875			return err
 876		}
 877		auctionVariables.Outbidding, err = c.AuctionGetOutbidding()
 878		if err != nil {
 879			return err
 880		}
 881		auctionVariables.SlotDeadline, err = c.AuctionGetSlotDeadline()
 882		return err
 883	}); err != nil {
 884		return nil, err
 885	}
 886	return auctionVariables, nil
 887}
 888
 889var (
 890	logAuctionNewBid                = crypto.Keccak256Hash([]byte("NewBid(uint128,uint128,address)"))
 891	logAuctionNewSlotDeadline       = crypto.Keccak256Hash([]byte("NewSlotDeadline(uint8)"))
 892	logAuctionNewClosedAuctionSlots = crypto.Keccak256Hash([]byte("NewClosedAuctionSlots(uint16)"))
 893	logAuctionNewOutbidding         = crypto.Keccak256Hash([]byte("NewOutbidding(uint16)"))
 894	logAuctionNewDonationAddress    = crypto.Keccak256Hash([]byte("NewDonationAddress(address)"))
 895	logAuctionNewBootCoordinator    = crypto.Keccak256Hash([]byte("NewBootCoordinator(address)"))
 896	logAuctionNewOpenAuctionSlots   = crypto.Keccak256Hash([]byte("NewOpenAuctionSlots(uint16)"))
 897	logAuctionNewAllocationRatio    = crypto.Keccak256Hash([]byte("NewAllocationRatio(uint16[3])"))
 898	logAuctionSetCoordinator        = crypto.Keccak256Hash([]byte("SetCoordinator(address,address,string)"))
 899	logAuctionNewForgeAllocated     = crypto.Keccak256Hash([]byte("NewForgeAllocated(address,address,uint128,uint128,uint128,uint128)"))
 900	logAuctionNewDefaultSlotSetBid  = crypto.Keccak256Hash([]byte("NewDefaultSlotSetBid(uint128,uint128)"))
 901	logAuctionNewForge              = crypto.Keccak256Hash([]byte("NewForge(address,uint128)"))
 902	logAuctionHEZClaimed            = crypto.Keccak256Hash([]byte("HEZClaimed(address,uint128)"))
 903)
 904
 905// AuctionEventsByBlock returns the events in a block that happened in the
 906// Auction Smart Contract and the blockHash where the eents happened.  If there
 907// are no events in that block, blockHash is nil.
 908func (c *AuctionClient) AuctionEventsByBlock(blockNum int64) (*AuctionEvents, *ethCommon.Hash, error) {
 909	var auctionEvents AuctionEvents
 910	var blockHash ethCommon.Hash
 911
 912	query := ethereum.FilterQuery{
 913		FromBlock: big.NewInt(blockNum),
 914		ToBlock:   big.NewInt(blockNum),
 915		Addresses: []ethCommon.Address{
 916			c.address,
 917		},
 918		Topics: [][]ethCommon.Hash{},
 919	}
 920
 921	logs, err := c.client.client.FilterLogs(context.TODO(), query)
 922	if err != nil {
 923		return nil, nil, err
 924	}
 925	if len(logs) > 0 {
 926		blockHash = logs[0].BlockHash
 927	}
 928	for _, vLog := range logs {
 929		if vLog.BlockHash != blockHash {
 930			return nil, nil, ErrBlockHashMismatchEvent
 931		}
 932		switch vLog.Topics[0] {
 933		case logAuctionNewBid:
 934			var auxNewBid struct {
 935				Slot      *big.Int
 936				BidAmount *big.Int
 937				Address   ethCommon.Address
 938			}
 939			var newBid AuctionEventNewBid
 940			if err := c.contractAbi.Unpack(&auxNewBid, "NewBid", vLog.Data); err != nil {
 941				return nil, nil, err
 942			}
 943			newBid.BidAmount = auxNewBid.BidAmount
 944			newBid.Slot = new(big.Int).SetBytes(vLog.Topics[1][:]).Int64()
 945			newBid.Bidder = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
 946			auctionEvents.NewBid = append(auctionEvents.NewBid, newBid)
 947		case logAuctionNewSlotDeadline:
 948			var newSlotDeadline AuctionEventNewSlotDeadline
 949			if err := c.contractAbi.Unpack(&newSlotDeadline, "NewSlotDeadline", vLog.Data); err != nil {
 950				return nil, nil, err
 951			}
 952			auctionEvents.NewSlotDeadline = append(auctionEvents.NewSlotDeadline, newSlotDeadline)
 953		case logAuctionNewClosedAuctionSlots:
 954			var newClosedAuctionSlots AuctionEventNewClosedAuctionSlots
 955			if err := c.contractAbi.Unpack(&newClosedAuctionSlots, "NewClosedAuctionSlots", vLog.Data); err != nil {
 956				return nil, nil, err
 957			}
 958			auctionEvents.NewClosedAuctionSlots = append(auctionEvents.NewClosedAuctionSlots, newClosedAuctionSlots)
 959		case logAuctionNewOutbidding:
 960			var newOutbidding AuctionEventNewOutbidding
 961			if err := c.contractAbi.Unpack(&newOutbidding, "NewOutbidding", vLog.Data); err != nil {
 962				return nil, nil, err
 963			}
 964			auctionEvents.NewOutbidding = append(auctionEvents.NewOutbidding, newOutbidding)
 965		case logAuctionNewDonationAddress:
 966			var newDonationAddress AuctionEventNewDonationAddress
 967			newDonationAddress.NewDonationAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
 968			auctionEvents.NewDonationAddress = append(auctionEvents.NewDonationAddress, newDonationAddress)
 969		case logAuctionNewBootCoordinator:
 970			var newBootCoordinator AuctionEventNewBootCoordinator
 971			newBootCoordinator.NewBootCoordinator = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
 972			auctionEvents.NewBootCoordinator = append(auctionEvents.NewBootCoordinator, newBootCoordinator)
 973		case logAuctionNewOpenAuctionSlots:
 974			var newOpenAuctionSlots AuctionEventNewOpenAuctionSlots
 975			if err := c.contractAbi.Unpack(&newOpenAuctionSlots, "NewOpenAuctionSlots", vLog.Data); err != nil {
 976				return nil, nil, err
 977			}
 978			auctionEvents.NewOpenAuctionSlots = append(auctionEvents.NewOpenAuctionSlots, newOpenAuctionSlots)
 979		case logAuctionNewAllocationRatio:
 980			var newAllocationRatio AuctionEventNewAllocationRatio
 981			if err := c.contractAbi.Unpack(&newAllocationRatio, "NewAllocationRatio", vLog.Data); err != nil {
 982				return nil, nil, err
 983			}
 984			auctionEvents.NewAllocationRatio = append(auctionEvents.NewAllocationRatio, newAllocationRatio)
 985		case logAuctionSetCoordinator:
 986			var setCoordinator AuctionEventSetCoordinator
 987			if err := c.contractAbi.Unpack(&setCoordinator, "SetCoordinator", vLog.Data); err != nil {
 988				return nil, nil, err
 989			}
 990			setCoordinator.BidderAddress = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
 991			setCoordinator.ForgerAddress = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
 992			auctionEvents.SetCoordinator = append(auctionEvents.SetCoordinator, setCoordinator)
 993		case logAuctionNewForgeAllocated:
 994			var newForgeAllocated AuctionEventNewForgeAllocated
 995			if err := c.contractAbi.Unpack(&newForgeAllocated, "NewForgeAllocated", vLog.Data); err != nil {
 996				return nil, nil, err
 997			}
 998			newForgeAllocated.Bidder = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
 999			newForgeAllocated.Forger = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
1000			newForgeAllocated.SlotToForge = new(big.Int).SetBytes(vLog.Topics[3][:]).Int64()
1001			auctionEvents.NewForgeAllocated = append(auctionEvents.NewForgeAllocated, newForgeAllocated)
1002		case logAuctionNewDefaultSlotSetBid:
1003			var auxNewDefaultSlotSetBid struct {
1004				SlotSet          *big.Int
1005				NewInitialMinBid *big.Int
1006			}
1007			var newDefaultSlotSetBid AuctionEventNewDefaultSlotSetBid
1008			if err := c.contractAbi.Unpack(&auxNewDefaultSlotSetBid, "NewDefaultSlotSetBid", vLog.Data); err != nil {
1009				return nil, nil, err
1010			}
1011			newDefaultSlotSetBid.NewInitialMinBid = auxNewDefaultSlotSetBid.NewInitialMinBid
1012			newDefaultSlotSetBid.SlotSet = auxNewDefaultSlotSetBid.SlotSet.Int64()
1013			auctionEvents.NewDefaultSlotSetBid = append(auctionEvents.NewDefaultSlotSetBid, newDefaultSlotSetBid)
1014		case logAuctionNewForge:
1015			var newForge AuctionEventNewForge
1016			newForge.Forger = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
1017			newForge.SlotToForge = new(big.Int).SetBytes(vLog.Topics[2][:]).Int64()
1018			auctionEvents.NewForge = append(auctionEvents.NewForge, newForge)
1019		case logAuctionHEZClaimed:
1020			var HEZClaimed AuctionEventHEZClaimed
1021			if err := c.contractAbi.Unpack(&HEZClaimed, "HEZClaimed", vLog.Data); err != nil {
1022				return nil, nil, err
1023			}
1024			HEZClaimed.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
1025			auctionEvents.HEZClaimed = append(auctionEvents.HEZClaimed, HEZClaimed)
1026		}
1027	}
1028	return &auctionEvents, &blockHash, nil
1029}