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.

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