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.

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