You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

873 lines
33 KiB

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