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.

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