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.

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